繁体   English   中英

TransactionScope中的DbContext + ObjectContext导致MDTC异常

[英]DbContext + ObjectContext in TransactionScope cause MDTC Exception

我的项目中有一个旧的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异常吗?

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

我与EF的经验是,它只能重新使用当前连接时的ConnectionString(正常的一个entityconnectionstring内)是完全相同 如果只有一个差异,则该事务将被提升为 分布式事务 ,该事务必须由系统启用,而对于您而言,则不是。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM