管理EntityFramework和EnterpriseLibrary的DatabaseFactory之间的事务

时间:2012-06-20 22:32:29

标签: entity-framework transactions enterprise-library transactionscope

我正在使用一组现有代码来管理单个事务中的多个数据库更新。这是一个简化的例子:

Database db = DatabaseFactory.CreateDatabase();
using (DbConnection dbConnection = db.CreateConnection())
{
    dbConnection.Open();
    DbTransaction dbTransaction = dbConnection.BeginTransaction();
    try
    {
        //do work
        dbTransaction.Commit();
    }
    catch (Exception ex)
    {
        dbTransaction.Rollback();
    }
}

我也在同一个项目中使用EntityFramework进行新开发。下面是我的存储库类的使用的简化示例:

List<ThingViewModel> things = new List<ThingViewModel>();
// populate list of things
IObjectRepository thingRepository = new ThingRepository();
thingRepository.AddThings(things);
thingRepository.Save();

我希望在“AddThings”中完成的工作在第一个代码块中作为事务的一部分发生。

是否有一些干净的方法将我的存储库模式混合到现有代码中,反之亦然?我还没有将现有代码重写为完全在EntityFramework中的可行性,所以我正在寻找一些临时方法。

我已经尝试将事务从旧代码传递到存储库,从而实现了EntityFramework,但这似乎不起作用。我还尝试将ObjectContext传回旧代码,以便在事务中登记它。这两种方法都不奏效。

我无法相信我是第一个在将现有代码迁移到EntityFramework时遇到这个障碍的人......必须有一些我不考虑的事情。

我将列出我在下面尝试的内容:

using (TransactionScope transactionScope = new TransactionScope())
{   
    Database db = DatabaseFactory.CreateDatabase();
    using (DbConnection dbConnection = db.CreateConnection())
    {
        dbConnection.Open();
        DbTransaction dbTransaction = dbConnection.BeginTransaction();
        try
        {
            //do work
            dbTransaction.Commit();
        }
        catch (Exception ex)
        {
            dbTransaction.Rollback();
        }
    }

    Thing thing = new Thing(){
        Prop1 = Val1,
        Prop2 = Val2
    };
    ThingObjectContext context = new ThingObjectContext();
    context.Things.AddObject(thing);
    context.SaveChanges();
    transactionScope.Complete();
}

这最后一个例子“有效”,它不能作为一个交易。当EF插入失败时,TransactionScope不会回滚EL命令。如果我没有将这些显式调用放到.Commit()和.SaveChanges(),则没有任何反应。如果可能的话,我真的希望能够共享相同的连接。我目前正在使用的另外两个变体是尝试在EF和EL之间使用相同的连接,以及在一侧或另一侧使用EnlistTransaction。绝对试图阻止它成为MSDTC - 不希望与此相关的额外开销。

2 个答案:

答案 0 :(得分:2)

使用TransactionScope而不是显式事务管理。您将简化整体代码,您所做的一切都应该自动检测并使用相同的事务。

答案 1 :(得分:1)

有什么方法可以在您的EL代码中调用Database.GetOpenConnection()而不是CreateConnection(),并传递您在things.Connection块内创建的TransactionScope?我没有对此进行测试,但这是我首先尝试的。