代码之家  ›  专栏  ›  技术社区  ›  Jared

SQL事务:在ASP.NET中实现的最佳方法

  •  4
  • Jared  · 技术社区  · 17 年前

    我有一个应用程序,它有许多不同类型的对象,每个对象都将自己保存回数据库。到目前为止,如果没有交易,这一切都很顺利,我也不想疯狂地增加交易。但有时需要在整个对象集合开始更新之前启动事务,以确保只有在集合中的所有对象都成功时才实际更新数据库。

    例如,假设我收集了一些苹果。向集合发出命令以更新所有苹果。[事务开始应该在这里]每个apples执行代码来更新自己。[此处应发生事务提交/回滚]。

    我有一个障碍,那就是每个更新现在都是原子的(不是显式包装在事务中)。我可以将一个ID传递给每个“apple”,以标识一个已存储在某种缓存中的事务,但这样会有缓存在更新期间失效并导致不必要的问题的风险。

    那么,最好的方法是什么呢?

    4 回复  |  直到 14 年前
        1
  •  4
  •   Jason Jackson    17 年前

    首先,我不会在页面中处理事务逻辑。编写某种类型的业务类来实现这一点——服务、数据实用程序类,这是可以从ASP.NET中抽象出来的。

    接下来,您可能会看到使用 交易范围 类(在System.Transactions命名空间中,引用System.Transactions.dll),如果您使用的数据库可以订阅像SQL Server这样的分布式事务。

    using(TransactionScope scope = new TransactionScope())
    {
      SaveObjectOne(); //these are just psuedo-code statements
      SaveObjectTwo(); //replace these with your code that saves various objs
      SaveObjectThree();
      scope.Complete(); //this commits the transaction, unless exception throws
    }
    

    TransactionScope实现IDisposable,因此 使用 电话 处置() 如果 完成() 从未打过电话。您确实需要启用分布式事务处理协调器来使用 交易范围 .

        2
  •  1
  •   Martin Brown    17 年前

    OP说集合管理事务中所有其他对象的保存,因此很明显将事务代码放在这里。如果您使用的是ADO.NET,那么打开连接并开始集合中的事务,然后将其传递给其他每个对象似乎是最简单的选项。我假设这里的每个对象都继承自一个层父类型类,而您使用的是SQL Server。

    public void Save()
    {
        using (SqlConnection connection = new SqlConnection("Connection String"))
        {
            using (SqlTransaction trans = connection.BeginTransaction())
            {
                foreach (BusinessObject obj in this) 
                { 
                    obj.Save(connection); 
                } 
                trans.Commit();
            }            
        }
    }
    
        3
  •  1
  •   Jason Plank Maksim Kondratyuk    14 年前

    ADO.NET 2.0中的事务非常简单 我建议使用TransactionScope,让框架为您管理事务:

    阅读所有相关内容 on MSDN :

    交易流管理

    事务范围可以直接嵌套 间接地。直接作用域嵌套只是一个嵌套的作用域 在另一个内部,如示例5所示。

    例5。直接作用域嵌套

    using(TransactionScope scope1 = new TransactionScope())
    {
       using(TransactionScope scope2 = new TransactionScope())
       {
          scope2.Complete();
       }
       scope1.Complete();
    }
    

    当调用使用 TransactionScope 从使用其自身作用域的方法中 案件与 RootMethod() 在示例6中。

    例6。间接范围嵌套

    void RootMethod()
    {
       using(TransactionScope scope = new TransactionScope())
       {
          /* Perform transactional work here */
          SomeMethod();
          scope.Complete();
       }
    }
    
    void SomeMethod()
    {
       using(TransactionScope scope = new TransactionScope())
       {
          /* Perform transactional work here */
          scope.Complete();
       }
    }
    
        4
  •  0
  •   Paul Kapustin    17 年前
    1. 我更喜欢声明性事务,而不是尝试手动DB事务。
    2. 正如MitchWheat已经提到的,事务具有上下文和基于连接,因此它将包括在页面/方法中发生的更改,如果一切正常,则提交,如果有异常,则回滚。
    3. 我可能错了 ,但我感觉“页面事务”使用的是.NET 1.1中的企业服务模型,并通过msdtc(分布式事务协调器,注册的COM+服务)工作…
    4. 对于.NET 2.0中的声明性事务,我更喜欢System.Transactions和LTM(轻量级事务管理器)。
    5. 我更喜欢SpRun.NET框架事务(可用于ADO.NET和NHiBiad版本),因为我相信它们支持更好的基于AOP(面向方面编程)的关注点分离,您不必将代码与事务代码耦合,而且主要是因为这些人已经在Java中做了很多年的事务。我只是相信他们知道该怎么做。
    推荐文章