c# - Entity Framework 4 and Async/TPL/Multi Threaded calls -
i looking advice calling entity framework 4 model using modern tpl (task parallel library). appreciate looks implemented in ef6 not have option upgrade entity framework 6 yet. hoping there within code manage , getting grips tpl.
i typically calling loads triggered treeview. however, nature of tree calling data access same entityobject types. doing follows in node expanded event:
var synchronizationcontext = taskscheduler.fromcurrentsynchronizationcontext(); task.factory.startnew(() => explorerviewmodel.getcontracts(parentnode.tag project).tolist()) .continuewith(cw => { populatecontracts(parentnode, cw.result); }, synchronizationcontext);
where explorerviewmodel.getcontracts call dbcontext. explorerviewmodel single instance within windows form. explorerviewmodel has single dbcontext instance.
it throwing following exception:
system.argumentexception unhandled user code hresult=-2147024809 message=an item same key has been added. source=mscorlib stacktrace: @ system.throwhelper.throwargumentexception(exceptionresource resource) @ system.collections.generic.dictionary`2.insert(tkey key, tvalue value, boolean add) @ system.data.objects.objectstatemanager.addstatemanagertypemetadata(entityset entityset, objecttypemapping mapping) @ system.data.objects.objectstatemanager.getoraddstatemanagertypemetadata(type entitytype, entityset entityset) @ system.data.objects.objectstatemanager.addentry(ientitywrapper wrappedobject, entitykey passedkey, entityset entityset, string argumentname, boolean isadded) @ system.data.common.internal.materialization.shaper.handleentityappendonly[tentity](func`2 constructentitydelegate, entitykey entitykey, entityset entityset) @ lambda_method(closure , shaper ) @ system.data.common.internal.materialization.coordinator`1.readnextelement(shaper shaper) @ system.data.common.internal.materialization.shaper`1.simpleenumerator.movenext() @ system.data.objects.dataclasses.relatedend.merge[tentity](ienumerable`1 collection, mergeoption mergeoption, boolean setisloaded) @ system.data.objects.dataclasses.entitycollection`1.load(list`1 collection, mergeoption mergeoption) @ system.data.objects.dataclasses.entitycollection`1.load(mergeoption mergeoption) @ system.data.objects.dataclasses.relatedend.load() @ acmedev.myapp.efdal.entity.project.get_contractlist() in k:\tfs\myapp\current\data\source\acmedev.myapp.efdal\entity\project.generated.cs:line 667 @ 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 @ acmedev.myapp.viewmodels.mainexplorerviewmodel.getcontracts(project project) in k:\tfs\myapp\current\myapp\source\acmedev.myapp.viewmodels\mainexplorerviewmodel.cs:line 611 @ 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 @ system.threading.tasks.task`1.innerinvoke() @ system.threading.tasks.task.execute() innerexception:
there large number of data being retrieved loads can slow. showing busy indicator on tree flag user, testing out async parts type.
i can use lock { }
within static
methods of repository myapprepository
, wonder if there nice way. wouldn't work calling relational objects can call parent.childrenlist.where(x => ...)
in other scenarios might want go async
.
explorerviewmodel single instance within windows form. explorerviewmodel has single dbcontext instance.
it sounds has single static
instance of dbcontext
, causing problem. can have getcontracts
method create new dbcontext
instance each invocation?
you typically should not have ef dbcontext live long. declaring dbcontext instance static
field or property bad idea, leads problem describing above others. reason because static
members have 1 instance shared collaborators. when happens, run concurrency issues poor dbcontext
, trying too many clients.
so, instead of this:
public class explorerviewmodel { private static somedbcontext _mydbcontext = new somedbcontext(); public static object getcontracts(project project) { _mydbcontext.dosomething(); ... return result; } }
...try this:
public class explorerviewmodel { public static object getcontracts(project project) { using (var mydbcontext = new somedbcontext()) { mydbcontext.dosomething(); ... return result; } } }
this way, each thread own dbcontext instance disposed of when thread finished using it.
i can use lock { } within static methods of repository myapprepository, wonder if there nice way.
the "nice" way not have static
methods on myapprepository
. instead, use instances of object, , have each scope own instance. sounds misusing static
types.
Comments
Post a Comment