在.NET 中使用Oracle數(shù)據(jù)庫事務

2010-08-28 10:48:27來源:西部e網(wǎng)作者:

了解在 Visual Basic .NET 和 C# 編寫數(shù)據(jù)庫事務的基礎(chǔ)知識。

本文相關(guān)下載:
· 示例代碼
· ODP.NET
· Oracle 數(shù)據(jù)庫 10g
· Microsoft .NET 框架和 SDK

在本文中,您將了解到如何在 Visual Basic .NET (VB.NET) 和 Visual C# .NET (C#) 中使用數(shù)據(jù)庫事務。具體來講,您將系統(tǒng)學習數(shù)據(jù)庫事務、在 .NET 程序中使用 OracleTransaction 對象以及如何設置事務保存點。本文中引用的所有腳本和文件都在這里提供。本文假定您大體上熟悉 C# 和 VB.NET 編程。

所需軟件

如果您要跟隨我們逐步完成本文中給出的示例,那么您需要安裝以下軟件:

  • Windows NT 4.0、Windows 2000、Windows XP Professional 或 Windows Server 2003
  • 能夠訪問一個已安裝的 Oracle 數(shù)據(jù)庫(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 或更高版本)

如果您打算使用企業(yè)服務事務或分布式事務來開發(fā)和運行應用程序,那么您還需要安裝 Oracle Services for Microsoft Transaction Server(10.1.0.2.0 或更高版本)。

您需要分別下載和安裝 .NET 框架以及 SDK(先安裝框架)。您還需要下載和安裝 Oracle 數(shù)據(jù)庫 10g,它包括 Oracle Data Provider for .NET (ODP.NET)。您可以選擇在不同計算機或同一計算機上安裝 ODP.NET 和數(shù)據(jù)庫服務器。

注意:ODP.NET 驅(qū)動程序針對 Oracle 數(shù)據(jù)庫訪問進行了優(yōu)化,因此可以獲得最佳性能,并且它們還支持 Oracle 數(shù)據(jù)庫的豐富特性,如 BFILE、BLOB、CLOB、XMLType 等。如果您正在開發(fā)基于 Oracle 數(shù)據(jù)庫的 .NET 應用程序,那么就特性和性能來講,ODP.NET 無疑是最佳的選擇。

數(shù)據(jù)庫模式設置

首先,您需要設置數(shù)據(jù)庫模式,在此我們使用一個簡化的 Web 商店示例。您必須首先創(chuàng)建一個名為 store 的用戶并按以下方式將所需的權(quán)限授予該用戶(您必須首先以擁有 CREATE USER 權(quán)限的用戶身份登錄數(shù)據(jù)庫才能創(chuàng)建用戶):

CREATE USER store IDENTIFIED BY store;
GRANT connect, resource TO store;

注意:您會在源代碼文件 db1.sql 中找到前兩個語句和該部分中出現(xiàn)的設置 store 模式的其他語句。

接下的語句以 store 用戶身份進行連接:

CONNECT store/store;

以下語句創(chuàng)建了所需的兩個數(shù)據(jù)庫表,名稱分別為 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 用戶創(chuàng)建了這些數(shù)據(jù)庫表,那么您將需要修改示例配置文件(您稍后將看到)中的模式名稱。

表 product_types 用于存儲示例在線商店可能庫存的產(chǎn)品類型的名稱,表 products 包含了所銷售產(chǎn)品的詳細信息。

下面的 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;

接下來,您將了解有關(guān)數(shù)據(jù)庫事務的內(nèi)容。

數(shù)據(jù)庫事務簡介

數(shù)據(jù)庫事務是由一組 SQL 語句組成的一個邏輯工作單元。您可以把事務看作是一組不可分的 SQL 語句,這些語句作為一個整體永久記錄在數(shù)據(jù)庫中或一并撤銷。比如在銀行帳戶之間轉(zhuǎn)移資金:一條 UPDATE 語句將從一個帳戶的資金總數(shù)中減去一部分,另一條 UPDATE 語句將把資金加到另一個帳戶中。減操作和加操作必須永久記錄在數(shù)據(jù)庫中,或者必須一并撤銷 — 否則將損失資金。這個簡單的示例僅使用了兩條 UPDATE 語句,但一個更實際的事務可能包含許多 INSERT、UPDATEDELETE 語句。

要永久記錄一個事務中的 SQL 語句的結(jié)果,您可以通過 COMMIT 語句來執(zhí)行提交。要撤銷 SQL 語句的結(jié)果,您可以使用 ROLLBACK 語句來執(zhí)行回滾,這會把所有的行重設為它們原來的狀態(tài)。只要您事先沒有與數(shù)據(jù)庫斷開,則您在執(zhí)行回滾之前所做的任何修改都將被撤銷。您還可以設置一個保存點,以便將事務回滾至該特定的點,同時保持事務中的其他語句原封不動。

在 C# 和 VB.NET 中使用數(shù)據(jù)庫事務

您可以使用 OracleTransaction 類的一個對象來表示一個事務。OracleTransaction 類包含多個屬性,其中的兩個為 Connection(指定與事務關(guān)聯(lián)的數(shù)據(jù)庫連接)和 IsolationLevel(指定事務隔離級別);本文稍后將向您介紹更多有關(guān)事務隔離級別的內(nèi)容。

OracleTransaction 類包含許多操控事務的方法。您可以使用 Commit() 方法永久提交 SQL 語句,并可以使用 Rollback() 撤銷這些語句。您還可以使用 Save() 在事務中設置一個保存點。

我現(xiàn)在將帶著您逐步完成兩個示例程序 — 一個用 C# 編寫 (TransExample1.cs),另一個用 VB.NET 編寫 (TransExample1.vb)。這些程序演示了如何執(zhí)行一個包含了兩條 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 步

創(chuàng)建一個 OracleConnection 對象連接到 Oracle 數(shù)據(jù)庫,然后打開該連接。

在 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 屬性指定了您所要連接到的模式的數(shù)據(jù)庫用戶和口令。Data Source 屬性指定了數(shù)據(jù)庫的 Oracle Net 服務名稱;初始數(shù)據(jù)庫的默認服務名稱為 ORCL。如果您使用的不是初始數(shù)據(jù)庫,或者您的服務名稱不同,那么您需要在程序中修改 Data Source 屬性的設置。

第 2 步

創(chuàng)建一個 OracleTransaction 對象,然后調(diào)用 OracleConnection 對象的 BeginTransaction() 方法啟動事務。

在 C# 中:

OracleTransaction myOracleTransaction =
myOracleConnection.BeginTransaction();

In VB.NET:

Dim myOracleTransaction As OracleTransaction = _
myOracleConnection.BeginTransaction()

第 3 步

創(chuàng)建一個 OracleCommand 對象,用于存儲 SQL 語句。

在 C# 中:

OracleCommand myOracleCommand = myOracleConnection.CreateCommand();

在 VB.NET 中:

Dim myOracleCommand As OracleCommand =
myOracleConnection.CreateCommand

因為 OracleCommand 對象使用 OracleConnection 對象的 CreateCommand() 方法創(chuàng)建的,所以它自動使用在第 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() 方法提交數(shù)據(jù)庫中的事務。

在 C# 中:

myOracleTransaction.Commit();

在 VB.NET 中:

myOracleTransaction.Commit()

在完成 Commit() 方法之后,由 INSERT 語句添加的兩行將在數(shù)據(jù)庫中永久記錄。

第 9 步

使用 Close() 方法關(guān)閉 OracleConnection 對象。

在 C# 中:

myOracleConnection.Close();

在 VB.NET 中:

myOracleConnection.Close()

編譯并運行示例程序

要編譯 C# 示例程序,您可以使用 csc 命令運行 C# 編譯器。因為程序使用 Oracle Data Access DLL,所以您應使用 /r 選項指定該 DLL 的完整路徑,例如:

 
csc TransExample1.cs /r:C:\oracle\product\10.1.0\
Client_1\bin\Oracle.DataAccess.dll

注意:您需要用您計算機上的相應路徑來替換該 DLL 的路徑。此外,如果您的計算機找不到 csc 編譯器,那么您可能需要運行 Microsoft sdkvars.bat 腳本來首先設置 .NET SDK 的環(huán)境變量;您可以在安裝 .NET SDK 的 bin 目錄中找到該腳本。

如果您遇到以下錯誤:

Example1.cs(10,7):error CS0246:The type or namespace name 'Oracle'
could not be found (are you missing a using directive or an assembly reference?)

這說明您沒有在編譯命令中正確指定 Oracle Data Access DLL。(有關(guān)設置的信息,請參閱 John Paul Cook 的技術(shù)文章“在 Oracle 數(shù)據(jù)庫上構(gòu)建 .NET 應用程序”。)

下面是用于編譯 VB.NET 程序的等價命令:

vbc TransExample1.vb /r:C:\oracle\product\10.1.0\
Client_1\bin\Oracle.DataAccess.dll /r:system.dll /r:system.data.dll

接下來,輸入以下命令,運行示例:

TransExample1

您將看到程序的輸出。不過,如果您遇到類似以下的異常:

An exception was thrown
Message = ORA-12514:TNS:listener does not currently know 
of service requested in connect descriptor

這說明 OracleConnection 對象的連接字符串中的 Data Source 的設置不正確。您應當咨詢您的 DBA 或查閱 Oracle Net 文檔以獲得更多詳細信息。

如果您使用的是 VS .NET,那么您可以遵循以下指示來編譯和運行 C# 程序 TransExample1.cs:

  1. 創(chuàng)建一個新的 C# 控制臺應用程序。File>New Project,然后選擇 Visual C# Projects,Console Application。
  2. 將項目命名為 TransExample1。
  3. 用 TransExample1.cs 中的代碼替換 VS .NET 生成的所有代碼。
  4. 選擇 Project>Add Reference 添加對 Oracle.DataAccess.dll 的引用,然后瀏覽至您安裝 ODP.NET 的目錄(在我的計算機上,它是 C:\oracle\product\10.1.0\Client_1\bin\Oracle.DataAccess.dll),然后雙擊 Oracle.DataAccess.dll。
  5. 選擇 Debug>Start without Debugging 運行該程序。

要編譯和運行 TransExample1.vb,您可以執(zhí)行類似的一系列步驟,但第 1 步應選擇一個 Visual Basic 控制臺應用程序,并在第 3 步用 TransExample1.vb 中的代碼替換生成的代碼。

查看程序的運行結(jié)果

當您運行完 C# 或 VB .NET 程序時,您可以在 SQL*Plus 中使用以下 SELECT 語句查看事務的結(jié)果:

SELECT p.product_id, p.product_type_id, pt. name, p.name, p.description, p.price
FROM products p, product_types pt
WHERE p.product_type_id = pt.product_type_id
AND p.product_id = 5;

您將看到以下結(jié)果:

PRODUCT_ID PRODUCT_TYPE_ID NAME       NAME
---------- --------------- ---------- -----------------------
DESCRIPTION                                             PRICE
-------------------------------------------------- ----------
5               3 Magazine   Oracle Magazine
Magazine about Oracle                                    4.99

接下來,您將了解如何設置事務保存點。

在 .NET 程序中設置事務保存點

正如本文前面所提到的那樣,您可以設置一個保存點,以便將事務回滾至該特定的點,同時保持事務中的其他語句原封不動。您可以使用 OracleTransaction 類的 Save() 方法在事務中設置保存點。

如果您有一個非常長的事務并且希望能夠僅回滾到某個特定的時間點,那么您可能要使用保存點。例如,您可能想對 10 個產(chǎn)品做一些更改,然后設置一個保存點,然后再對另 10 個產(chǎn)品做更改;如果您在進行第二批更改時出現(xiàn)了錯誤,那么您可以回滾至保存點,使您的第一批更改原封不動。

我將帶您逐步完成演示如何使用保存點的 C# (TransExample2.cs) 示例程序和 VB.NET (TransExample2.vb) 示例程序中的相關(guān)新步驟。這些程序向表 products 中添加一行,設置一個保存點,向表 products 中添加另一行,回滾至保存點,然后從表 products 中讀取這些行。在回滾至保存點后,只有添加到表 products 中的第一行保留了下來:第二行將已被刪除。

第 1 到第 3 步與“在 C# 和 VB.NET 中使用數(shù)據(jù)庫事務”部分中所示的步驟相同,因此在這里將其省略。

第 4 步

向表 products 中添加一行,該行的產(chǎn)品 ID 為 6。

在 C# 中:

myOracleCommand.CommandText =
"INSERT INTO products (" +
"  product_id, product_type_id, name, description, price" +
") VALUES (" +
"  6, 2, 'Man from Another World', 'Man from Venus lands on Earth', 24.99" +
  ")";
myOracleCommand.ExecuteNonQuery();

在 VB.NET 中:

myOracleCommand.CommandText = _
"INSERT INTO products (" & _
"  product_id, product_type_id, name, description, price" & _
") VALUES (" & _
"  6, 2, 'Man from Another World', 'Man from Venus lands on Earth', 24.99" & _
  ")"
myOracleCommand.ExecuteNonQuery()

第 5 步

使用 OracleTransaction 的 Save() 方法設置一個名為 SaveProduct 的保存點。

在 C# 中:

myOracleTransaction.Save("SaveProduct");

在 VB.NET 中:

myOracleTransaction.Save("SaveProduct")

第 6 步

向表 products 中添加另一行,該行的產(chǎn)品 ID 為 7。

在 C# 中:

myOracleCommand.CommandText =
"INSERT INTO products (" +
"  product_id, product_type_id, name, description, price" +
") VALUES (" +
"  7, 2, 'Z-Files', 'Mysterious stories', 14.99" +
  ")";
myOracleCommand.ExecuteNonQuery();

在 VB.NET 中:

myOracleCommand.CommandText = _
"INSERT INTO products (" & _
"  product_id, product_type_id, name, description, price" & _
") VALUES (" & _
"  7, 2, 'Z-Files', 'Mysterious stories', 14.99" & _
  ")"
myOracleCommand.ExecuteNonQuery() 

第 7 步

回滾到先前在第 5 步中設置的 SaveProduct 保存點。

在 C# 中:

myOracleTransaction.Rollback("SaveProduct");

在 VB.NET 中:

myOracleTransaction.Rollback("SaveProduct")

完成回滾后,在第 6 步中添加的第二行已被刪除,而在第 4 步中添加的第一行保留了下來。

TransExample2.cs 和 TransExample2.vb 中剩下的步驟顯示表 products 的內(nèi)容,回滾整個事務并從數(shù)據(jù)庫斷開。

用于 Microsoft Transaction Server 的 Oracle 事務服務的快速說明

Microsoft Transaction Server 是一個運行在互聯(lián)網(wǎng)或網(wǎng)絡服務器上的專有事務處理系統(tǒng)。Microsoft Transaction Server 為客戶端計算機部署和管理應用程序和數(shù)據(jù)庫事務請求。

Microsoft Transaction Server 是以服務器為中心的三層體系結(jié)構(gòu)模型的一個組件。這種方法實現(xiàn)了將應用程序的表示、業(yè)務邏輯和數(shù)據(jù)元素清晰地分布到在一個網(wǎng)絡中連接的不同計算機上。無需專門集成,您就可以在與 Oracle 數(shù)據(jù)庫服務器 8.0.6 版或更高版本連接的 Microsoft Transaction Server 中部署一個組件,但首先您必須安裝 Oracle Services for Microsoft Transaction Server。

結(jié)論

在本文中,您系統(tǒng)學習了在 .NET 程序中使用數(shù)據(jù)庫事務。您了解了如何創(chuàng)建 OracleTransaction 對象并用它們將事務提交給數(shù)據(jù)庫,如何使用保存點部分回滾一個事務,以及 Oracle 數(shù)據(jù)庫如何分離并發(fā)事務。


技術(shù)顧問兼作家 Jason Price 是 Microsoft 認證專家、Oracle 認證數(shù)據(jù)庫管理員和應用程序開發(fā)人員,具有十多年的軟件行業(yè)從業(yè)經(jīng)驗。他撰寫了《Oracle 數(shù)據(jù)庫 10g SQL》(McGraw-Hill/Osborne,2004)、《精通 C# 數(shù)據(jù)庫編程》(Sybex,2004)、《精通 Visual C# .NET 編程》(Sybex,2003)、《Oracle9i JDBC 編程》(McGraw-Hill/Osborne,2002)和《使用 Oracle SQLJ 進行 Java 編程》(O'Reilly,2001)。

關(guān)鍵詞:Oracle

贊助商鏈接: