【问题标题】:Managing transactions between EntityFramework and EnterpriseLibrary's DatabaseFactory管理 EntityFramework 和 EnterpriseLibrary 的 DatabaseFactory 之间的事务
【发布时间】:2012-06-20 22:32:29
【问题描述】:

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

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 - 不希望与此相关的额外开销。

【问题讨论】:

    标签: entity-framework transactions enterprise-library transactionscope


    【解决方案1】:

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

    【讨论】:

    • 感谢您的意见 - 我根据您的建议更新了我的原始帖子。仍在玩几种不同的变体,但没有任何成功。我可以让 EL 或 EF 工作,但不能在同一个事务中一起工作。
    • 如果完全删除显式 DbTransaction 对象会怎样?实际上,并且完全删除连接的显式创建 - Entlib 将自动为您打开和关闭连接,并将事务范围用作事务边界。
    • 问题在于 EL 中的代码是所有业务对象使用的通用模式的一部分,因此它无处不在。我正在寻找一些解决方案,使我们能够在短时间内将 EL 代码与新的 EF 代码混合。不过,这看起来不太可能。
    【解决方案2】:

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

    【讨论】:

    • 如果你能发布一些代码 sn-p 那就太棒了。目前,我无法找到一种方法来引用另一个与 EL 的连接,就像您建议使用“GetOpenConnection()”一样,而且 EL 和 EF 之间的连接类型似乎不兼容(DbConnection v. EntityConnection)。跨度>
    • 两者使用的事务类型相同(DbTransaction v. Transaction)
    • 抱歉,我想不出办法让这项工作像我想象的那样简单。看起来您正前往 MSDTC-ville。
    猜你喜欢
    • 1970-01-01
    • 2014-03-22
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-19
    相关资源
    最近更新 更多