0

我正在寻找一些使用现代TPL(任务并行库)调用实体框架4模型的建议。我很欣赏这看起来是在EF6中实现的,但目前还没有升级到实体框架6的选项。我希望在我的代码中可以做些事情来管理这个问题,并且我正在掌握TPL。实体框架4和异步/ TPL /多线程调用

我通常调用从TreeView触发的加载。但是,树的本质是调用相同EntityObject类型的数据访问。我在节点扩展事件如下所示:

​​

其中ExplorerViewModel.GetContracts将调用我的DbContext。 ExplorerViewModel是Windows窗体中的单个实例。 ExplorerViewModel有一个DbContext实例。

它抛出以下异常:

System.ArgumentException was unhandled by user code 
    HResult=-2147024809 
    Message=An item with the same key has already been added. 
    Source=mscorlib 
    StackTrace: 
     at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) 
     at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) 
     at System.Data.Objects.ObjectStateManager.AddStateManagerTypeMetadata(EntitySet entitySet, ObjectTypeMapping mapping) 
     at System.Data.Objects.ObjectStateManager.GetOrAddStateManagerTypeMetadata(Type entityType, EntitySet entitySet) 
     at System.Data.Objects.ObjectStateManager.AddEntry(IEntityWrapper wrappedObject, EntityKey passedKey, EntitySet entitySet, String argumentName, Boolean isAdded) 
     at System.Data.Common.Internal.Materialization.Shaper.HandleEntityAppendOnly[TEntity](Func`2 constructEntityDelegate, EntityKey entityKey, EntitySet entitySet) 
     at lambda_method(Closure , Shaper) 
     at System.Data.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper shaper) 
     at System.Data.Common.Internal.Materialization.Shaper`1.SimpleEnumerator.MoveNext() 
     at System.Data.Objects.DataClasses.RelatedEnd.Merge[TEntity](IEnumerable`1 collection, MergeOption mergeOption, Boolean setIsLoaded) 
     at System.Data.Objects.DataClasses.EntityCollection`1.Load(List`1 collection, MergeOption mergeOption) 
     at System.Data.Objects.DataClasses.EntityCollection`1.Load(MergeOption mergeOption) 
     at System.Data.Objects.DataClasses.RelatedEnd.Load() 
     at ACMEDev.MyApp.EFDAL.Entity.Project.get_ContractList() in k:\TFS\MyApp\Current\Data\source\ACMEDev.MyApp.EFDAL\Entity\Project.Generated.cs:line 667 
     at ACMEDev.MyApp.Data.Entity.MyAppRepository.GetContracts(Project project, MyAppEntities context) in k:\TFS\MyApp\Current\MyApp\source\ACMEDev.MyApp.Data\Entity\MyAppRepository.cs:line 43 
     at ACMEDev.MyApp.ViewModels.MainExplorerViewModel.GetContracts(Project project) in k:\TFS\MyApp\Current\MyApp\source\ACMEDev.MyApp.ViewModels\MainExplorerViewModel.cs:line 611 
     at ACMEDev.MyApp.Controls.Navigation.MyAppExplorerTree.<>c__DisplayClass17.<PopulateNode>b__4() in k:\TFS\MyApp\Current\MyApp\source\ACMEDev.MyApp.Controls\Navigation\MyAppExplorerTree.cs:line 347 
     at System.Threading.Tasks.Task`1.InnerInvoke() 
     at System.Threading.Tasks.Task.Execute() 
    InnerException: 

有被检索,因此负载可能会很慢了大量的数据。我将在树上显示一个繁忙的指示器,将其标记给用户,但是我在输入时测试了异步部分。

我可以在我的资源库MyAppRepositorystatic方法中使用lock { },但不知道是否有一个好方法。这对于调用关系对象无效,在其他情况下,我可能会呼叫parent.ChildrenList.Where(x => ...),我可能想要去async

回答

0

ExplorerViewModel是Windows窗体中的单个实例。 ExplorerViewModel有一个DbContext实例。

听起来像这样有一个单一的static实例DbContext,这可能会导致问题。你可以用GetContracts方法为每个调用创建一个new DbContext实例吗?

您通常不应该有EF DbContext长时间存在。将DbContext实例声明为static字段或属性通常是一个非常糟糕的主意,这会导致您在上面描述的问题以及其他问题。原因是因为static成员只有1个由所有协作者共享的实例。发生这种情况时,遇到并行性问题,对于太多的客户而言,这种做法太差了。

所以,与其这样:

public class ExplorerViewModel 
{ 
    private static SomeDbContext _myDbContext = new SomeDbContext(); 

    public static object GetContracts(Project project) 
    { 
     _myDbContext.DoSomething(); 
     ... 
     return result; 
    } 
} 

...尝试这样的事:

public class ExplorerViewModel 
{ 
    public static object GetContracts(Project project) 
    { 
     using (var myDbContext = new SomeDbContext()) 
     { 
      myDbContext.DoSomething(); 
      ... 
      return result; 
     } 
    } 
} 

这样,每个线程将获得自己的DbContext实例,它被妥善处置时的线程完成使用它。

我可以在我的存储库的静态方法中使用锁{} MyAppRepository,但不知道是否有一个好方法。

“好”的方法是在MyAppRepository上没有任何static方法。相反,使用该对象的实例,并让每个范围都有自己的实例。这听起来像你在滥用static类型。

+0

问题是从下到上!我的环境贯穿于应用程序的生命周期中。我的实体不是POCO。它们都来自我使用nHydrate生成的EntityObject。这些在整个应用程序中使用。不幸的是,这是2011/2012年编码的方式。存储库的想法是一个解决方案。我需要更好的方式去做我认为将会是一件大事的事情。 – Andez 2014-12-30 19:59:01