【问题标题】:DbContext + ObjectContext in TransactionScope cause MDTC ExceptionTransactionScope 中的 DbContext + ObjectContext 导致 MDTC 异常
【发布时间】:2023-03-04 13:18:01
【问题描述】:

我的项目中有一个旧的 ObjectContext 和几个新的 DbContext(即用于不同目的的 BoundedContext)。 有时我需要在一个事务中提交其中少数几个的更改。在某些情况下,我需要保存来自 ObjectContext 和 DbContext 的数据。 在 EF 5.0 中,为了避免 MSDC,我编写了一些包装器

public class ContextUnitOfWork
{
    List<IContext> ContextList;
    public ContextUnitOfWork()
    {
        ContextList = new List<IContext>(); 
    }
    public void RegisterContext(IContext Context)
    {
        ContextList.Add(Context);
    }
    public bool IsDisposed
    {
        get
        {
            return ContextList.Any(x => x.IsDisposed);
        }
    }
    public bool HasChangedEntities
    {
        get
        {
            return ContextList.Any(x => x.HasChangedEntities);
        }
    }
    public void Commit()
    {
        bool HasDbContext = ContextList.OfType<System.Data.Entity.DbContext>().Any();
        try
        {
            if (HasDbContext)
            {
                ContextList.ForEach(x =>
                {

                    if (x is System.Data.Entity.DbContext)
                    {
                        (x as System.Data.Entity.DbContext).Database.Connection.Open();
                    }
                    else if (x is System.Data.Objects.ObjectContext)
                    {
                        ((System.Data.Objects.ObjectContext)x).Connection.Open();
                    }

                });
            }

            using (var scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required,
    new System.Transactions.TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
            {
                ContextList.ForEach(x => x.Commit());
                scope.Complete();
            }
        }
        catch (System.Data.UpdateException uex)
        {
            var ErrorList = uex.StateEntries.Select(x => x.Entity).ToList(); 
        }
        finally
        {
            if (HasDbContext)
            {
                ContextList.ForEach(x =>
                {
                    if (x is System.Data.Entity.DbContext)
                    {
                        (x as System.Data.Entity.DbContext).Database.Connection.Close();
                    }
                    else if (x is System.Data.Objects.ObjectContext)
                    {
                        ((System.Data.Objects.ObjectContext)x).Connection.Close();
                    }
                });
            };

        }
    }
}

但在 EntityFramework 6.0.1 中它不起作用。 ObjectContext 提交成功,但是当 DbContext 调用 SaveChanges() 时,EntityException 类型的异常带有文本 “EnlistTransaction 上的基础提供商失败。”并且内部预期包含{“分布式事务管理器 (MSDTC) 的网络访问已被禁用。请使用组件服务管理工具在 MSDTC 的安全配置中启用 DTC 以进行网络访问。”}

在一个事务中提交上下文并避免 MDTC 异常的任何想法?

【问题讨论】:

  • 英文内部异常“分布式事务管理器 (MSDTC) 的网络访问已被禁用。请使用组件服务管理工具在 MSDTC 的安全配置中启用 DTC 以进行网络访问。” Можешь поправить)

标签: c# entity-framework dbcontext objectcontext


【解决方案1】:

您正在尝试在本地事务中运行所有内容,即使使用相同类型的多个上下文也非常棘手。这样做的原因是您不能与同一个本地事务有多个打开的连接。如果前一个上下文仍然存在,通常会为下一个上下文打开一个新连接。这将触发将本地事务提升为分布式事务。

我对 EF 的体验是,只有当连接字符串(实体连接字符串中的正常连接字符串)完全相同时,它才会重新使用当前连接。如果存在单一差异,则交易将提升分布式交易,该交易必须由系统启用,在您的情况下,它不是。 p>

此外,如果您已经在执行查询,并且仍在从该查询中读取结果,那么同时启动另一个查询(当然)将需要另一个连接,因此,本地事务将被提升为分布式事务。

你能检查连接字符串是否相同吗?如果重新使用当前连接,我仍然会感到惊讶。

【讨论】:

  • 连接字符串完全相同。它看起来像“数据源=MyDataBase;初始目录=MyDataBase;集成安全=True;Pooling=True;应用程序名称=MyApp”
  • 如果没有手动打开连接并且连接字符串绝对相同,它可以工作。谢谢马腾。
  • 如果您手动打开连接,并推迟关闭连接直到提交,实际上,需要多个打开的连接,这需要分布式事务。本地事务无法处理。
猜你喜欢
  • 2013-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多