【问题标题】:Entity Framework and SQL Server Savepoints实体框架和 SQL Server 保存点
【发布时间】:2011-08-08 20:24:59
【问题描述】:

我向different question 询问了有关嵌套事务的问题,我的问题的答案足以让我意识到我问的问题很糟糕。所以这是一个更好的问题。

如何使用基于 Entity Framework 4.0 构建的 DAL 有效地实现 SQL Server 保存点(link 1link 2)?

我想编写以下代码并让它以 SQL Server 的 SAVEPOINTS 的方式工作

public void Bar()
{
  using (var ts = new TransactionScope())
  {
    var ctx = new Context();
    DoSomeStuff(ctx);

    bool isSuccessful;

    using (var spA = new SavePoint("A")) // <-- this object doesn't really exist, I don't think
    {
      isSuccessful = DoSomeOtherStuff(ctx);
      if (isSuccessful)
        spA.Complete(); // else rollback bo prior to the beginning of this using block
    }

    Log(ctx, isSuccessful);

    ts.Complete();
  }
}

有没有一种方法可以做任何与此类似的事情,或者其他与 EF4 配合得很好的事情? (我们使用自定义的自追踪 POCO 实体)

【问题讨论】:

    标签: .net .net-4.0 entity-framework-4 sql-server-2008-r2 savepoints


    【解决方案1】:

    这不是一个完整的答案,但我怀疑这样的事情可能会走上正确的道路。我的问题是I'm not entirely sure how to get a SqlTransaction while in a TransactionScope

    /// <summary>
    /// Makes a code block transactional in a way that can be partially rolled-back. This class cannot be inherited.
    /// </summary>
    /// <remarks>
    /// This class makes use of SQL Server's SAVEPOINT feature, and requires an existing transaction.
    /// If using TransactionScope, utilize the DependentTransaction class to obtain the current Transaction that this class requires.
    /// </remarks>
    public sealed class TransactionSavePoint : IDisposable
    {
        public bool IsComplete { get; protected set; }
        internal SqlTransaction Transaction { get; set; }
        internal string SavePointName { get; set; }
    
        private readonly List<ConnectionState> _validConnectionStates = new List<ConnectionState>
                                                                            {
                                                                                ConnectionState.Open
                                                                            };
    
        public TransactionSavePoint(SqlTransaction transaction, string savePointName)
        {
            IsComplete = false;
            Transaction = transaction;
            SavePointName = savePointName;
    
            if (!_validConnectionStates.Contains(Transaction.Connection.State))
            {
                throw new ApplicationException("Invalid connection state: " + Transaction.Connection.State);
            }
    
            Transaction.Save(SavePointName);
        }
    
        /// <summary>
        /// Indicates that all operations within the savepoint are completed successfully.
        /// </summary>
        public void Complete()
        {
            IsComplete = true;
        }
    
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            if (!IsComplete)
            {
                Transaction.Rollback(SavePointName);
            }
        }
    }
    

    这将被这样使用,与 TransactionScope 非常相似:

    SqlTransaction myTransaction = Foo();
    
    using (var tsp = new TransactionSavePoint(myTransaction , "SavePointName"))
    {
      try
      {
        DoStuff();
        tsp.Complete
      }
      catch (Exception err)
      {
        LogError(err);
      }
    }
    

    【讨论】:

    • 我将此标记为答案,因为这是我能找到的最好的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多