Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DbContext+;TransactionScope中的ObjectContext导致MDTC异常_C#_Entity Framework_Dbcontext_Objectcontext - Fatal编程技术网

C# DbContext+;TransactionScope中的ObjectContext导致MDTC异常

C# DbContext+;TransactionScope中的ObjectContext导致MDTC异常,c#,entity-framework,dbcontext,objectcontext,C#,Entity Framework,Dbcontext,Objectcontext,我的项目中有一个旧的ObjectContext和几个新的DbContext(即用于不同目的的BoundedContext)。 有时我需要在一个事务中提交其中几个事务的更改。在某些情况下,我需要持久化ObjectContext和DbContext中的数据。 在EF 5.0中,为了避免出现MSDC,我编写了一些包装 public class ContextUnitOfWork { List<IContext> ContextList; public ContextUnit

我的项目中有一个旧的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();
                    }
                });
            };

        }
    }
}
公共类上下文工作
{
列表上下文列表;
公共上下文工作()
{
ContextList=新列表();
}
公共无效注册表上下文(IContext上下文)
{
添加(上下文);
}
公共图书馆被公布
{
得到
{
返回ContextList.Any(x=>x.IsDisposed);
}
}
公共场所有变化
{
得到
{
返回ContextList.Any(x=>x.HasChangedEntities);
}
}
公共无效提交()
{
bool HasDbContext=ContextList.OfType().Any();
尝试
{
if(HasDbContext)
{
ContextList.ForEach(x=>
{
if(x是System.Data.Entity.DbContext)
{
(x为System.Data.Entity.DbContext).Database.Connection.Open();
}
else if(x是System.Data.Objects.ObjectContext)
{
((System.Data.Objects.ObjectContext)x).Connection.Open();
}
});
}
使用(var范围=新的System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required),
新System.Transactions.TransactionOptions{IsolationLevel=System.Transactions.IsolationLevel.ReadCommitted})
{
ForEach(x=>x.Commit());
scope.Complete();
}
}
catch(System.Data.UpdateException uex)
{
var ErrorList=uex.StateEntries.Select(x=>x.Entity.ToList();
}
最后
{
if(HasDbContext)
{
ContextList.ForEach(x=>
{
if(x是System.Data.Entity.DbContext)
{
(x为System.Data.Entity.DbContext).Database.Connection.Close();
}
else if(x是System.Data.Objects.ObjectContext)
{
((System.Data.Objects.ObjectContext)x).Connection.Close();
}
});
};
}
}
}
但在EntityFramework6.0.1中,它不起作用。ObjectContext提交成功,但当DbContext调用SaveChanges()时,类型为EntityException的异常将显示文本 “基础提供程序在登记事务时失败,”,内部预期包含{“分布式事务管理器(MSDTC)的网络访问已被禁用。请使用组件服务管理工具在MSDTC的安全配置中为网络访问启用DTC。”}


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

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

我对EF的经验是,只有当connectionstring(entityconnectionstring中的正常连接)完全相同时,EF才会重新使用当前连接。如果存在单一差异,则事务将升级为分布式事务,该事务必须由系统启用,而在您的情况下,则不是

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


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

英语内部异常“分布式事务管理器(MSDTC)的网络访问已禁用。请使用组件服务管理工具在MSDTC的安全配置中为网络访问启用DTC。”连接串完全相同。它看起来像“数据源=MyDataBase;初始目录=MyDataBase;集成安全性=True;池=True;应用程序名称=MyApp”,如果不手动打开连接,并且如果连接字符串完全相同,它就可以工作。谢谢Maarten。如果您手动打开连接,并将关闭连接推迟到提交,那么实际上需要多个打开的连接,这需要分布式事务。本地事务无法处理此问题。