C# 实体框架5线程敏捷性

C# 实体框架5线程敏捷性,c#,entity-framework,entity-framework-5,async-await,nullreferenceexception,C#,Entity Framework,Entity Framework 5,Async Await,Nullreferenceexception,EntityFramework代码的深层抛出了一个NullReferenceException(EF bug?),但我的问题是关于EntityFramework(v5)和WebAPI异步控制器操作的 在这里很难重新创建复制,但代码本质上做了以下工作: public class AController : ApiController { private IUow _uow; //among other things, a DbContext // DI ctor publ

EntityFramework代码的深层抛出了一个NullReferenceException(EF bug?),但我的问题是关于EntityFramework(v5)和WebAPI异步控制器操作的

在这里很难重新创建复制,但代码本质上做了以下工作:

public class AController : ApiController
{
    private IUow _uow; //among other things, a DbContext 
    // DI ctor
    public AController(IUow uow)
    {
        _uow = uow; 
    }

    [HttpPost]
    public async Task<HttpResponseMessage> Post(Model model)
    {
        Entity e = _uow.Entity.GetById(model.id);
        await IO_Ops_Async(model); 
        new ModelAdapter().UpdateEntity(entity, model);
        _uow.Commit(); <- EXCEPTION THROWN DURING THIS CALL - see below
        ... // do something with the return result
    }
}

由于IO完成,
wait
之后有一个隐式线程切换。另外,EF5可能无法处理此问题,因为它使用线程本地存储

在这种情况下,Oto、EF6.x(尤其是最新版本)应该可以正常工作

相关的:

更新了以回应评论:

因为async/await基础结构应该负责处理和流 ExecutionContext(线程本地存储和其他“上下文”)。我 我这样问是为了让我能够做出有教育意义的改变,并保护环境 异步/等待实现,处理任何特定的事情 打破EF

EF5源代码不是开源的(与EF6不同),因此我不能100%确定,但我怀疑EF5明确使用TLS(即
ThreadStatic
ThreadLocal
无法通过
ExecutionContext
自动传递所有TLS属性,这将是一个巨大的突破性变化,并对现有代码构成安全威胁(更不用说在技术上可能无法实现这一点)

ExecutionContext
捕获和流。此子集没有文档记录,但您可以了解更多信息


在多个线程之间传递其静态属性是特定类实现的责任,为此有
CallContext.LogicalSetData
/
CallContext.LogicalGetData
。我相信这就是EF6在引擎盖下所做的。

好吧,EF5可能无法处理这个问题。我看到过类似的评论(有些是你的),但我想知道你是否有细节。因为async/await基础结构假定负责并流式处理ExecutionContext(线程本地存储和其他“上下文”)。我这样做是为了让我能够做出有教育意义的更改,并保留async/await实现,以处理破坏EF的任何具体问题。感谢您添加信息。早些时候,我能够找到pre-v.6 System.Data.Entity.dll的参考源(不确定它是4还是5),但我假设您是指EntityFramework.dll,对吗?@G.Stoynev,我认为这两个dll仍在EF5+中使用,请检查。
System.NullReferenceException: Object reference not set to an instance of an object.\r\n   
at System.Data.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   
at System.Data.Objects.DataClasses.EntityReference`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   
at System.Data.Objects.DataClasses.RelatedEnd.WalkObjectGraphToIncludeAllRelatedEntities(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   
at System.Data.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   
at System.Data.Objects.DataClasses.EntityCollection`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   
at System.Data.Objects.DataClasses.RelatedEnd.WalkObjectGraphToIncludeAllRelatedEntities(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   
at System.Data.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   
at System.Data.Objects.DataClasses.EntityReference`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   
at System.Data.Objects.DataClasses.RelatedEnd.WalkObjectGraphToIncludeAllRelatedEntities(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)\r\n   
at System.Data.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedTarget, Boolean applyConstraints, Boolean addRelationshipAsUnchanged, Boolean relationshipAlreadyExists, Boolean allowModifyingOtherEndOfRelationship, Boolean forceForeignKeyChanges)\r\n   
at System.Data.Objects.ObjectStateManager.PerformAdd(IEntityWrapper wrappedOwner, RelatedEnd relatedEnd, IEntityWrapper entityToAdd, Boolean isForeignKeyChange)\r\n   
at System.Data.Objects.ObjectStateManager.PerformAdd(IList`1 entries)\r\n   
at System.Data.Objects.ObjectStateManager.DetectChanges()\r\n   
at System.Data.Entity.Internal.InternalContext.GetStateEntries(Func`2 predicate)\r\n   
at System.Data.Entity.Infrastructure.DbChangeTracker.Entries()\r\n