博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
dotConnect for Oracle入门指南(六):使用事务
阅读量:5756 次
发布时间:2019-06-18

本文共 7529 字,大约阅读时间需要 25 分钟。

hot3.png

【下载最新版本】

(原名OraDirect.NET)建立在ADO.NET技术上,为基于Oracle数据库的应用程序提供完整的解决方案。它为设计应用程序结构带来了新的方法,提高工作效率,使数据库应用程序的开发更简便。

使用事务

  • 了解事务
  • 本地事务
  • OCI模式下的分布式事务
  • 直接模式下的分布式事务

了解事务

事务是一个或多个被视为单个工作单元的操作,完全完成或完全无效(“全部或无”)。如果事务中某一点发生故障,则所有更新都可以回滚到其事务前状态。事务必须符合ACID属性-原子性、一致性、隔离性和持久性,以确保数据一致性。

如果一个事务涉及同一数据库中的多个表,那么PL/SQL中的显式事务通常执行得更好。您可以在SQL中使用Commit和Rollback语句分别修复和放弃当前PL/SQL块中以前的命令。

否则,可以通过设计用于Oracle数据库的库/程序集中的特殊命令类来实现具有普通SQL的事务。例如,您可以使用devart.data.oracle.oraclecommand:在oraclecommand的连接上启动事务,通过此oraclecommand执行多个SQL语句,并在必要时提交/回滚所有操作。请参阅本地事务主题中的示例。

本文描述了从.NET代码(不包含envolving PL/SQL事务)操作事务的方法——这是处理事务最常见的情况。关于您的任务,您可以选择要实现的事务类型-本地或分布式。当事务是单阶段事务并且由数据库直接处理时,被认为是本地事务的事务。分布式事务是一个影响多个资源的事务,它由事务监视器协调,并使用故障保护机制(如两阶段提交)来解决事务。

注意:Oracle不支持SQL Server中使用的可升级事务,分布式事务的实现在OCI和Direct模式下有所不同。还要考虑到TransactionScope(分布式事务)仅在处理时完成。

本地事务

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

转载于:https://my.oschina.net/u/4009527/blog/3004360

你可能感兴趣的文章
PyCharm切换解释器
查看>>
12.12日个人工作总结
查看>>
jmp far ptr s所对应的机器码
查看>>
css详解1
查看>>
【转载】Presentation at from Yoshua Bengio
查看>>
MySQL类型转换
查看>>
HashSet HashMap 源码阅读笔记
查看>>
变量声明提升1
查看>>
轻量级的Java 开发框架 Spring
查看>>
JS之路——浏览器window对象
查看>>
Chrome教程(二)使用ChromeDevTools命令菜单运行命令
查看>>
数据结构及算法基础--快速排序(Quick Sort)(二)优化问题
查看>>
你对position的了解到底有多少?
查看>>
随笔2013/2/19
查看>>
Windows Phone的Silverlight Toolkit 安装及其使用
查看>>
DBS:同学录
查看>>
Mysql备份系列(1)--备份方案总结性梳理
查看>>
[CareerCup] 1.6 Rotate Image 翻转图像
查看>>
jQuery中$.fn的用法示例介绍
查看>>
Python中的画图初体验
查看>>