dotConnect for Oracle入門指南(六):使用事務

【下載dotConnect for Oracle最新版本】數據庫

dotConnect for Oracle(原名OraDirect.NET)創建在ADO.NET技術上,爲基於Oracle數據庫的應用程序提供完整的解決方案。它爲設計應用程序結構帶來了新的方法,提升工做效率,使數據庫應用程序的開發更簡便。服務器

使用事務oracle

  • 瞭解事務
  • 本地事務
  • OCI模式下的分佈式事務
  • 直接模式下的分佈式事務

瞭解事務

事務是一個或多個被視爲單個工做單元的操做,徹底完成或徹底無效(「所有或無」)。若是事務中某一點發生故障,則全部更新均可以回滾到其事務前狀態。事務必須符合ACID屬性-原子性、一致性、隔離性和持久性,以確保數據一致性。分佈式

若是一個事務涉及同一數據庫中的多個表,那麼PL/SQL中的顯式事務一般執行得更好。您能夠在SQL中使用Commit和Rollback語句分別修復和放棄當前PL/SQL塊中之前的命令。性能

不然,能夠經過設計用於Oracle數據庫的庫/程序集中的特殊命令類來實現具備普通SQL的事務。例如,您可使用devart.data.oracle.oraclecommand:在oraclecommand的鏈接上啓動事務,經過此oraclecommand執行多個SQL語句,並在必要時提交/回滾全部操做。請參閱本地事務主題中的示例。spa

本文描述了從.NET代碼(不包含envolving PL/SQL事務)操做事務的方法——這是處理事務最多見的狀況。關於您的任務,您能夠選擇要實現的事務類型-本地或分佈式。當事務是單階段事務而且由數據庫直接處理時,被認爲是本地事務的事務。分佈式事務是一個影響多個資源的事務,它由事務監視器協調,並使用故障保護機制(如兩階段提交)來解決事務。設計

注意:Oracle不支持SQL Server中使用的可升級事務,分佈式事務的實如今OCI和Direct模式下有所不一樣。還要考慮到TransactionScope(分佈式事務)僅在處理時完成。code

本地事務

dotConnect for Oracle具備用於執行本地事務的OracleTransaction對象。當一個鏈接對象上的多個操做應做爲一個事務執行時,使用OracleTransaction。應用程序經過對OracleConnection對象調用BeginTransaction來建立OracleTransaction對象。與事務相關聯的全部後續操做(例如,提交或停止事務)都在OracleTransaction對象上執行。OracleConnection和OracleTransaction之間的相關性始終爲1:1。所以,一次只能爲單獨的OracleConnection建立一個OracleTransaction。對象

例子:事務

下面的示例建立OracleConnection和OracleTransaction。它還演示瞭如何使用BeginTransaction、Commit和Rollback方法。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

public void RunOracleTransaction(string myConnString)

{

  OracleConnection myConnection = new OracleConnection(myConnString);

  myConnection.Open();

  OracleCommand myCommand = new OracleCommand();

  OracleTransaction myTrans;

  // Start a local transaction

  myTrans = myConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);

  // Assign transaction object for a pending local transaction

  myCommand.Transaction = myTrans;

  myCommand.Connection = myConnection;

  try

  {

    myCommand.CommandText = "INSERT INTO Test.Dept(DeptNo, DName) Values(50, 'DEVELOPMENT')";

    myCommand.ExecuteNonQuery();

    myCommand.CommandText = "INSERT INTO Test.Dept(DeptNo, DName) Values(60, 'PRODUCTION')";

    myCommand.ExecuteNonQuery();

    myTrans.Commit();

    Console.WriteLine("Both records are written to database.");

  }

  catch(Exception e)

  {

    myTrans.Rollback();

    Console.WriteLine(e.ToString());

    Console.WriteLine("Neither record was written to database.");

  }

  finally

  {

    myConnection.Close();

  }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

Public Sub RunOracleTransaction(ByVal myConnString As String)

  Dim myConnection As New OracleConnection(myConnString)

  myConnection.Open()

  Dim myCommand As New OracleCommand

  Dim myTrans As OracleTransaction

  ' Start a local transaction

  myTrans = myConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted)

  ' Assign transaction object for a pending local transaction

  myCommand.Transaction = myTrans

  myCommand.Connection = myConnection

  Try

    myCommand.CommandText = "INSERT INTO Test.Dept(DeptNo, DName) Values(50, 'DEVELOPMENT')"

    myCommand.ExecuteNonQuery()

    myCommand.CommandText = "INSERT INTO Test.Dept(DeptNo, DName) Values(60, 'PRODUCTION')"

    myCommand.ExecuteNonQuery()

    myTrans.Commit()

    Console.WriteLine("Both records are written to database.")

  Catch As Exception

    myTrans.Rollback()

    Console.WriteLine(e.ToString())

    Console.WriteLine("Neither record was written to database.")

  Finally

    myConnection.Close()

  End Try

End Sub

OCI模式下的分佈式事務

若是要將對多個鏈接對象執行的操做放入同一分佈式事務中,則須要將它們登記到TransactionScope中。它能夠經過鏈接字符串的Enlist參數或OracleConnection類的Enlist Transaction方法來完成。

OCI模式徹底支持TransactionScope和兩階段提交。

System.Transactions.TransactionScope類經過在分佈式事務中隱式登記鏈接,使代碼塊成爲事務性的。必須在TransactionScope標記的代碼塊末尾調用完整方法。當程序執行離開代碼塊時調用Dispose方法,若是不調用完整方法,則會致使事務中斷。若是引起了致使代碼離開做用域的異常,則認爲該事務已停止。

建議使用using塊以確保在退出using塊時對TransactionScope對象調用Dispose方法。提交或回滾掛起的事務失敗會嚴重下降性能,由於TransactionScope的默認超時爲一分鐘。若是不使用using語句,則必須在try塊中執行全部工做,並在finally塊中顯式調用Dispose方法。

若是TransactionScope內發生異常,則該事務將標記爲不一致並被放棄。在釋放TransactionScope時回滾。若是沒有發生異常,則參與事務提交。

例子:

下面的示例演示TransactionScope的用法。必須添加對System.Transactions.dll程序集的引用,才能使用System.Transactions命名空間。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

using (TransactionScope transScope = new TransactionScope())

{

    using (OracleConnection connection1 = new

       OracleConnection(connectString1))

    {

        // Opening connection1 automatically enlists it in the

        // TransactionScope as a distributed transaction.

        connection1.Open();

 

        // Do work in the first connection.

 

        // Assumes conditional logic in place where the second

        // connection will only be opened as needed.

        using (OracleConnection connection2 = new

            OracleConnection(connectString2))

        {

            // Open the second connection, which enlists the

            // second connection to a full distributed transaction.

            connection2.Open();

 

            // Do work in the second connection.

        }

    }

    //  The Complete method commits the transaction.

    transScope.Complete();

// The result of transaction will be available at the database after

// disposing TransactionScope

}

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

Using transScope As New TransactionScope()

    Using connection1 As New OracleConnection(connectString1)

        ' Opening connection1 automatically enlists it in the

        ' TransactionScope as a distributed transaction.

        connection1.Open()

 

        ' Do work in the first connection.

 

        ' Assumes conditional logic in place where the second

        ' connection will only be opened as needed.

        Using connection2 As New OracleConnection(connectString2)

            ' Open the second connection, which enlists the

            ' second connection and promotes the transaction to

            ' a full distributed transaction.

            connection2.Open()

 

            ' Do work in the second connection.

 

        End Using

    End Using

 

    ' The Complete method commits the transaction.

    transScope.Complete()

' The result of transaction will be available at the database after

' disposing TransactionScope

End Using

直接模式下的分佈式事務

直接模式鏈接也登記在分佈式事務中。但在這種狀況下,將只仿真TransactionScope支持,由於在直接模式下不支持兩階段提交。將爲其範圍內的每一個鏈接建立單獨的OracleTransaction。這些OracleTransaction的工做不徹底同步:

若是對某個已登記鏈接的操做引起異常,則可使用try…catch塊輕鬆處理此狀況。只需將transactionscope.complete()放在try塊的最後一行。所以,任何異常狀況下的代碼執行都不會到達complete()行,分佈式事務也不會被提交。另外一方面,可能會發生如下狀況:在兩個已登記到TransactionScope鏈接上的全部操做都會成功地執行,沒有例外,但若是在處理TransactionScope(當操做實際提交到數據庫時)時,第一個OracleTransaction失敗(例如,服務器故障或終止數據庫會話),則e第二個OracleTransaction仍處於提交狀態,而且TransactionScope成功完成(沒有其第一個OracleTransaction)。

一個OracleTransaction的更改在當前TransactionScope的其餘OracleTransactions中不可見。例如,第70條記錄將在OCI模式下的TransactionScope中插入和更新,但僅在直接模式下插入(未更新):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

using (TransactionScope ts = new TransactionScope()) {

    using (OracleConnection connection = new OracleConnection(connStr)) {

        connection.Open();

        OracleCommand command = connection.CreateCommand();

        command.CommandText = "insert into dept(deptno,dname,loc) values (70,'Development','London')";

        command.ExecuteNonQuery();

    }

    using (OracleConnection connection2 = new OracleConnection(connStr)){

        connection2.Open();

        OracleCommand command2 = connection2.CreateCommand();

        command2.CommandText = "update dept set loc='New York' where deptno=70";

        command2.ExecuteNonQuery();

    }

    ts.Complete();

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Using ts As New TransactionScope()

    Using connection As New OracleConnection(connStr)

        connection.Open()

        Dim Command As OracleCommand = connection.CreateCommand()

        Command.CommandText = "insert into dept(deptno,dname,loc) values (70,'Development','London')"

        Command.ExecuteNonQuery()

    End Using

    Using connection2 As New OracleConnection(connStr)

        connection2.Open()

        Dim Command2 As OracleCommand = connection2.CreateCommand()

        Command2.CommandText = "update dept set loc='New York' where deptno=70"

        command2.ExecuteNonQuery()

    End Using

    ts.Complete()

End Using

相關文章
相關標籤/搜索