C# CodeFirst Lazy Loading with MVVM

偶尔善良 提交于 2019-12-13 00:53:05

问题


I have a moderate-sized CodeFirst application which has been written using fairly strict MVVM ( which has a C#/WPF front-end and CodeFirst to MS SQL Server backend).

I have written a load of helper classes in the Model, which create the DbContext, load objects and so on. I used to do this by generating a single DbContext per thread (in a static function) and obtaining that reference from the appropriate load function (Person.Load() would call GetDbContext). This worked quite nicely alongside lazy loading.

It got to a point where there were some bugs in my code due to the use of this single DbContext per thread and so decided to switch to the better practice of a single DbContext per work unit, with loading code inside a 'using' statement. There seems to be negligible real-world speed difference.

My problem now is one of lazy loading. Because when the properties on 'Person' are accessed, the DbContext no longer exists, 'automagic' lazy loading does not happen.

What's the best way to get around this? I can manually call the Model in my ViewModel when one of these properties is accessed, but I'm ending up with calls to the Model everywhere and doing things manually that should happen behind the scenes. It also means that things seem less coordinated - I'm ending up with detached POCO's and it seems more of a mess that when I was originally using one DbContext per thread! The normalized structure of the database does mean that there are lots of these sorts of relationships.

The other (very resource-hungry) method could be to store a DbContext with each loaded object so that lazy loading still works...

Thanks in advance for any advice. Adam


回答1:


One static DBContext is indeed generally not a good solution (especially if you have more than one client that accesses to the DB), so the refactoring you've started definitely makes sense.

Now you have a problem with lazy loading, because once you've reached the end of the using scope, you can't launch a SQL request anymore as the context has closed its connection to the DB server when it has been disposed.

The solution you're talking about

The other (very resource-hungry) method could be to store a DBContext with each loaded object so that lazy loading still works...

is actually what's happening under the hood. Each loaded entity that allows to lazy-load one of its navigation properties is related to Entity Framework (that's those proxy-object of a type generated at runtime that inherit from your POCOs), so it actually holds a reference to the DBContext already.

Which means, if you don't dispose your DBContext manually (with using), lazy-loading will still be available. This wouldn't be the solution to all your problems though, because you probably would have then to deal with multiple entities coming from different contexts, and this simply won't work easily (for example you can't add one entity coming from DBContext instance A into DBContext instance B).

Now, what's the solution then? Well, it probably will be complicated.

You currently have a 2-tiers application, i.e. your heavy WPF client directly communicates with the database. Lazy-loading is enabled, which means everywhere in your code (especially in the ViewModels), a SQL request could be sent to the DB server. This is actually far from the unit of work pattern that better works with a stateless 3-tier application. In such an application, each time you call a service you have a new "unit of work" and a new entity context instantiated.

If you were starting a new application, I would say: go for a 3-tier stateless application, shorten the EF context lifetime as much as possible, deactivate lazy-loading and work with detached entities everywhere in your code.

Now if you have already a lot of code, you probably have two options: either refactor it all with those ideas about context lifetime in mind, or make minor modifications to your current code to only fix the bugs you have right now with your context-per-thread pattern.



来源:https://stackoverflow.com/questions/21405637/c-sharp-codefirst-lazy-loading-with-mvvm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!