实体框架和SQL Server保存点 [英] Entity Framework and SQL Server Savepoints

查看:172
本文介绍了实体框架和SQL Server保存点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我曾询问有关嵌套交易的不同问题,并且我的问题的答案足够教育我帮我意识到我在问这个问题。所以这是一个更好的问题。



如何有效地实现SQL Server保存点(链接1 链接2 ),建立在Entity Framework 4.0上的DAL



我会喜欢写下面的代码,并使其工作的方式是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))//< - 这个对象并不真的存在,我不认为
{
isSuccessful = DoSomeOtherStuff(ctx);
if(isSuccessful)
spA.Complete(); // else rollback bo在开始之前使用块
}

Log(ctx,isSuccessful);

ts.Complete();
}
}

有没有办法做任何甚至接近类似于这一点,还是其他与EF4很好的游戏? (我们使用自定义的自我跟踪POCO实体)

解决方案

这不是一个完整的答案,但我怀疑这样的事情可能会走正确的道路。我的问题是我不完全确定如何在一个SqlTransaction TransactionScope

  ///< summary> 
///以可部分回滚的方式进行事务处理。这个类不能被继承。
///< / summary>
///< remarks>
///此类使用SQL Server的SAVEPOINT功能,并且需要现有的事务。
///如果使用TransactionScope,请使用DependentTransaction类来获取此类所需的当前事务。
///< / remarks>
public sealed class TransactionSavePoint:IDisposable
{
public bool IsComplete {get;保护套}
内部SqlTransaction事务{get;组; }
内部字符串SavePointName {get;组; }

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>
///表示保存点内的所有操作都已成功完成。
///< / summary>
public void Complete()
{
IsComplete = true;
}

///< summary>
///执行与释放,释放或重置非托管资源相关联的应用程序定义任务。
///< / summary>
public void Dispose()
{
if(!IsComplete)
{
Transaction.Rollback(SavePointName);
}
}
}

,与TransactionScope非常相似:

  SqlTransaction myTransaction = Foo(); 

使用(var tsp = new TransactionSavePoint(myTransaction,SavePointName))
{
try
{
DoStuff();
tsp.Complete
}
catch(异常错误)
{
LogError(err);
}
}


I asked a different question about Nested Transactions and the answer to my question educated me enough to help me realize I was asking the question poorly. So here's a better question.

How can I effectively implement SQL Server Savepoints (link 1, link 2) with a DAL built upon Entity Framework 4.0?

I would LIKE to write the following code and have it work in a way that SQL Server's 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();
  }
}

Is there such a way to do anything even close to resembling this, or something else that plays nicely with EF4? (we use custom self-tracking POCO entities)

解决方案

This isn't quite a full answer, but I suspect something like this might be going down the right path. My problem is that 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);
        }
    }
}

This would be consumed as such, very similarly to a TransactionScope:

SqlTransaction myTransaction = Foo();

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

这篇关于实体框架和SQL Server保存点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆