Sql Transactions:ASP.Net中实现的最佳方式

时间:2008-11-24 00:57:56

标签: asp.net database transactions

我有一个应用程序,它有许多不同类型的对象,每个对象都会自行返回db。到目前为止,这没有交易工作正常,我不打算去添加它们。但是,在整个对象集合开始更新之前,偶尔需要启动事务,以确保只有在集合中的所有对象都成功时才实际更新数据库。

例如,假设我有一系列苹果。该命令被发送到集合以更新所有苹果。 [事务开始应该在这里]每个苹果执行代码来更新自己。 [事务提交/回滚应该在这里发生]。

我遇到的问题是每个更新现在都是原子的(未明确包装在事务中)。我可以将一个id传递给每个“apple”以识别已经存储在某种缓存中的事务,但是存在缓存在更新期间无效并导致不必要问题的风险。

那么最好的方法是什么?

4 个答案:

答案 0 :(得分:4)

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

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

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,因此当使用调用 Dispose()时,如果从未调用 Complete(),事务将回滚。您需要启用分布式事务处理协调器以使用 TransactionScope

答案 1 :(得分:1)

OP表示集合管理事务中所有其他对象的保存,因此将事务代码放在此处似乎显而易见。如果您使用的是ADO.Net,那么打开连接并在集合中开始事务然后将其传递给其他每个对象似乎是最简单的选择。我假设这里的每个对象都继承自Layer Supertype Class,而你使用的是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();
        }            
    }
}

答案 2 :(得分:1)

ado.net 2.0中的交易非常简单 我建议使用transactionscope并让框架为您处理交易:

阅读所有相关信息on MSDN

  

交易流程管理

     

交易范围可以直接嵌套   和间接的。直接范围嵌套只是一个嵌套的范围   在另一个内部,如例5所示。

     

示例5.直接范围嵌套

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

调用使用a的方法时会发生间接作用域嵌套   TransactionScope来自使用其自己的范围的方法   示例6中RootMethod()的情况。

     

示例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();
   }
}

答案 3 :(得分:0)

  1. 我更倾向于声明性事务,而不是尝试进行手动数据库事务。
  2. 正如Mitch Wheat已经提到的,一个事务具有上下文并且是基于连接的,因此它将包括您在页面/方法中发生的更改,如果一切正常则提交,或者如果存在异常则回滚。
  3. 我可能在这里错了,但我感觉“页面事务”正在使用.NET 1.1中的Enterprise Services模型并通过MSDTC(分布式事务协调器,已注册的COM +服务)工作。
  4. 我更喜欢System.Transactions和LTM(轻量级事务管理器)用于.NET 2.0中的声明式事务
  5. 我更喜欢Spring.NET框架事务(可用于ADO.NET和NHibernate版本),因为我相信它们支持更好的基于AOP(面向方面​​编程)的关注点分离,您不必将代码与事务代码,主要是因为这些人已经在Java中进行了多年的交易,我只相信他们知道该怎么做。