在本文中,您将了解到如何在 Visual Basic .NET (VB.NET) 和 Visual C# .NET (C#) 中使用数据库事务。具体来讲,您将系统学习数据库事务、在 .NET 程序中使用 OracleTransaction 对象以及如何设置事务保存点。本文中引用的所有脚本和文件都在这里提供。本文假定您大体上熟悉 C# 和 VB.NET 编程。
所需软件
如果您要跟随我们逐步完成本文中给出的示例,那么您需要安装以下软件:
Windows NT 4.0、Windows 2000、Windows XP Professional 或 Windows Server 2003
能够访问一个已安装的 Oracle 数据库(Oracle8i 版本 3 8.1.7 或更高版本)
Oracle 客户机(版本 10.1.0.2.0 或更高版本)
Oracle Net(版本 10.1.0.2.0 或更高版本)
Oracle Data Providers for .NET(版本 10.1.0.2.0 或更高版本)
Microsoft .NET Framework(版本 1.0 或更高版本)
Microsoft .NET 框架 SDK(版本 1.0 或更高版本)
如果您打算使用企业服务事务或分布式事务来开发和运行应用程序,那么您还需要安装 Oracle Services for Microsoft Transaction Server(10.1.0.2.0 或更高版本)。
您需要分别下载和安装 .NET 框架以及 SDK(先安装框架)。您还需要下载和安装 Oracle 数据库 10g,它包括 Oracle Data Provider for .NET (ODP.NET)。您可以选择在不同计算机或同一计算机上安装 ODP.NET 和数据库服务器。
注意:ODP.NET 驱动程序针对 Oracle 数据库访问进行了优化,因此可以获得最佳性能,并且它们还支持 Oracle 数据库的丰富特性,如 BFILE、BLOB、CLOB、XMLType 等。如果您正在开发基于 Oracle 数据库的 .NET 应用程序,那么就特性和性能来讲,ODP.NET 无疑是最佳的选择。
数据库模式设置
首先,您需要设置数据库模式,在此我们使用一个简化的 Web 商店示例。您必须首先创建一个名为 store 的用户并按以下方式将所需的权限授予该用户(您必须首先以拥有 CREATE USER 权限的用户身份登录数据库才能创建用户):
CREATE USER store IDENTIFIED BY store;
GRANT connect, resource TO store;
注意:您会在源代码文件 db1.sql 中找到前两个语句和该部分中出现的设置 store 模式的其他语句。
接下的语句以 store 用户身份进行连接:
CONNECT store/store;
以下语句创建了所需的两个数据库表,名称分别为 product_types 和 products:
CREATE TABLE product_types (
product_type_id INTEGER
CONSTRAINT product_types_pk PRIMARY KEY,
name VARCHAR2(10) NOT NULL
);
CREATE TABLE products (
product_id INTEGER
CONSTRAINT products_pk PRIMARY KEY,
product_type_id INTEGER
CONSTRAINT products_fk_product_types
REFERENCES product_types(product_type_id),
name VARCHAR2(30) NOT NULL,
description VARCHAR2(50),
price NUMBER(5, 2)
);
注意:如果您在一个不同的模式中为 store 用户创建了这些数据库表,那么您将需要修改示例配置文件(您稍后将看到)中的模式名称。
表 product_types 用于存储示例在线商店可能库存的产品类型的名称,表 products 包含了所销售产品的详细信息。
下面的 INSERT 语句为表 product_types 和 products 添加行:
INSERT INTO product_types (
product_type_id, name
) VALUES (
1, 'Book'
);
INSERT INTO product_types (
product_type_id, name
) VALUES (
2, 'DVD'
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
1, 1, 'Modern Science', 'A description of modern science', 19.95
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
2, 1, 'Chemistry', 'Introduction to Chemistry', 30.00
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
3, 2, 'Supernova', 'A star explodes', 25.99
);
INSERT INTO products (
product_id, product_type_id, name, description, price
) VALUES (
4, 2, 'Tank War', 'Action movie about a future war', 13.95
);
COMMIT;
接下来,您将了解有关数据库事务的内容。
数据库事务简介
数据库事务是由一组 SQL 语句组成的一个逻辑工作单元。您可以把事务看作是一组不可分的 SQL 语句,这些语句作为一个整体永久记录在数据库中或一并撤销。比如在银行帐户之间转移资金:一条 UPDATE 语句将从一个帐户的资金总数中减去一部分,另一条 UPDATE 语句将把资金加到另一个帐户中。减操作和加操作必须永久记录在数据库中,或者必须一并撤销 ― 否则将损失资金。这个简单的示例仅使用了两条 UPDATE 语句,但一个更实际的事务可能包含许多 INSERT、UPDATE 和 DELETE 语句。
要永久记录一个事务中的 SQL 语句的结果,您可以通过 COMMIT 语句来执行提交。要撤销 SQL 语句的结果,您可以使用 ROLLBACK 语句来执行回滚,这会把所有的行重设为它们原来的状态。只要您事先没有与数据库断开,则您在执行回滚之前所做的任何修改都将被撤销。您还可以设置一个保存点,以便将事务回滚至该特定的点,同时保持事务中的其他语句原封不动。
在 C# 和 VB.NET 中使用数据库事务
您可以使用 OracleTransaction 类的一个对象来表示一个事务。OracleTransaction 类包含多个属性,其中的两个为 Connection(指定与事务关联的数据库连接)和 IsolationLevel(指定事务隔离级别);本文稍后将向您介绍更多有关事务隔离级别的内容。
OracleTransaction 类包含许多操控事务的方法。您可以使用 Commit() 方法永久提交 SQL 语句,并可以使用 Rollback() 撤销这些语句。您还可以使用 Save() 在事务中设置一个保存点。
我现在将带着您逐步完成两个示例程序 ― 一个用 C# 编写 (TransExample1.cs),另一个用 VB.NET 编写 (TransExample1.vb)。这些程序演示了如何执行一个包含了两条 INSERT 语句的事务。第一条 INSERT 语句将在表 product_types 中添加一行,第二条将在表 products 中添加一行。
导入命名空间
以下 C# 程序语句指定在程序中使用 System 和 Oracle.DataAcess.Client 命名空间:
using System;
using Oracle.DataAccess.Client;
下面是等价的 VB.NET 语句:
Imports System
Imports Oracle.DataAccess.Client
Oracle.DataAccess.Client 命名空间是 ODP.NET 的一部分,它包含许多类,其中有 OracleConnection、OracleCommand 和 OracleTransaction。示例程序用到了这些类。
第 1 步
创建一个 OracleConnection 对象连接到 Oracle 数据库,然后打开该连接。
在 C# 中:
OracleConnection myOracleConnection =
new OracleConnection(
"User Id=store;Password=store;Data Source=ORCL"
);
myOracleConnection.Open();
在 VB.NET 中:
Dim myOracleConnection As New OracleConnection( _
"User Id=store;Password=store;Data Source=ORCL")
myOracleConnection.Open()
User Id 和 Password 属性指定了您所要连接到的模式的数据库用户和口令。Data Source 属性指定了数据库的 Oracle Net 服务名称;初始数据库的默认服务名称为 ORCL。如果您使用的不是初始数据库,或者您的服务名称不同,那么您需要在程序中修改 Data Source 属性的设置。
第 2 步
创建一个 OracleTransaction 对象,然后调用 OracleConnection 对象的 BeginTransaction() 方法启动事务。
在 C# 中:
OracleTransaction myOracleTransaction =
myOracleConnection.BeginTransaction();
In VB.NET:
Dim myOracleTransaction As OracleTransaction = _
myOracleConnection.BeginTransaction()
第 3 步
创建一个 OracleCommand 对象,用于存储 SQL 语句。
在 C# 中:
OracleCommand myOracleCommand = myOracleConnection.CreateCommand();
在 VB.NET 中:
Dim myOracleCommand As OracleCommand =
myOracleConnection.CreateCommand
因为 OracleCommand 对象使用 OracleConnection 对象的 CreateCommand() 方法创建的,所以它自动使用在第 2 步中为 OracleConnection 对象设置的事务。
第 4 步
将 OracleCommand 对象的 CommandText 属性设为向表 product_types 中添加一行的第一条 INSERT 语句。
在 C# 中:
myOracleCommand.CommandText =
"INSERT INTO product_types (" +
" product_type_id, name" +
") VALUES (" +
" 3, 'Magazine'" +
")";
在 VB.NET 中:
myOracleCommand.CommandText = _
"INSERT INTO product_types (" & _
" product_type_id, name" & _
") VALUES (" & _
" 3, 'Magazine'" & _
")"
第 5 步
使用 OracleCommand 对象的 ExecuteNonQuery() 方法运行 INSERT 语句。
在 C# 中:
myOracleCommand.ExecuteNonQuery();
在 VB.NET 中:
myOracleCommand.ExecuteNonQuery()
第 6 和第 7 步
将 OracleCommand 对象的 CommandText 属性设为向表 Products 中添加一行的第二条 INSERT 语句,并运行它。
在 C# 中:
myOracleCommand.CommandText =
"INSERT INTO products (" +
" product_id, product_type_id, name, description, price" +
") VALUES (" +
" 5, 3, 'Oracle Magazine', 'Magazine about Oracle', 4.99" +
")";
myOracleCommand.ExecuteNonQuery();
在 VB.NET 中:
myOracleCommand.CommandText = _
"INSERT INTO products (" & _
" product_id, product_type_id, name, description, price" & _
") VALUES (" & _
" 5, 3, 'Oracle Magazine', 'Magazine about Oracle', 4.99" & _
")"
myOracleCommand.ExecuteNonQuery()
第 8 步
使用 OracleTransaction 对象的 Commit() 方法提交数据库中的事务。
在 C# 中:
myOracleTransaction.Commit();
在 VB.NET 中:
myOracleTransaction.Commit()
在完成 Commit() 方法之后,由 INSERT 语句添加的两行将在数据库中永久记录。
第 9 步
使用 Close() 方法关闭 OracleConnection 对象。
在 C# 中:
myOracleConnection.Close();
在 VB.NET 中:
myOracleConnection.Close()
编译并运行示例程序
要编译 C# 示例程序,您可以使用 csc 命