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

相关文章
相关标签/搜索