使用MVVM进行C#代码首次延迟加载

时间:2014-01-28 12:33:16

标签: c# entity-framework optimization mvvm code-first

我有一个中等大小的CodeFirst应用程序,它使用相当严格的MVVM(具有C#/ WPF前端和CodeFirst到MS SQL Server后端)编写。

我在Model中编写了一大堆辅助类,它们创建了DbContext,加载了对象等等。我曾经通过为每个线程(在静态函数中)生成单个DbContext并从适当的加载函数(Person.Load()调用GetDbContext)获取该引用来完成此操作。这与延迟装载一起工作得非常好。

由于每个线程都使用了这个单个DbContext,我的代码中出现了一些错误,所以决定切换到每个工作单元单个DbContext的更好实践,并在'using '声明。似乎可以忽略不计的现实速度差异。

我现在的问题是延迟加载。因为当访问'Person'上的属性时,DbContext不再存在,'自动'延迟加载不会发生。

解决这个问题的最佳方法是什么?当访问其中一个属性时,我可以在我的ViewModel中手动调用Model,但我最终会调用模型到处处理,并且手动执行应该在幕后执行的操作。这也意味着事情似乎不那么协调 - 我最终得到了分离的POCO,而且当我最初每个线程使用一个DbContext时,它似乎更加混乱!数据库的规范化结构确实意味着存在许多这种关系。

另一个(非常需要资源)的方法可能是为每个加载的对象存储一个DbContext,以便延迟加载仍然有效......

提前感谢任何建议。 亚当

1 个答案:

答案 0 :(得分:0)

一个静态DBContext确实通常不是一个好的解决方案(特别是如果你有多个访问数据库的客户端),所以你开始的重构肯定是有意义的。

现在您遇到了延迟加载的问题,因为一旦到达using范围的末尾,您就无法再启动SQL请求,因为上下文已关闭其与处置数据库服务器

您正在谈论的解决方案

  

另一种(非常耗费资源)方法可能是存储DBContext   与每个加载的对象,以便延迟加载仍然有效...

实际上是在幕后发生的事情。允许延迟加载其某个导航属性的每个加载实体都与实体框架(即在运行时生成的从您的POCO继承的类型的代理对象)相关,因此它实际上包含已经引用了DBContext

这意味着,如果您未手动处理DBContext(使用using),则仍然可以使用延迟加载。这不是解决所有问题的方法,因为你可能会处理来自不同环境的多个实体,而这根本不会轻易解决(例如你可以' t将DBContext实例A中的一个实体添加到DBContext实例B)。

现在,解决方案是什么?好吧,它可能会很复杂。

您目前拥有2层应用程序,即您的重型WPF客户端直接与数据库通信。启用了延迟加载,这意味着代码中的任何位置(特别是在ViewModels中)都可以将SQL请求发送到数据库服务器。这实际上远离工作单元模式,更好地适用于无状态3层应用程序。在这样的应用程序中,每次调用服务时,都会有一个新的“工作单元”和一个实例化的新实体上下文。

如果你正在开始一个新的应用程序,我会说:寻找一个3层无状态应用程序,尽可能缩短EF上下文生命周期,停用延迟加载并在代码中的任何地方使用分离的实体。

现在,如果您已经有很多代码,那么您可能有两个选择:要么完全重构这些关于上下文生命周期的想法,要么对您当前的代码进行微小的修改,以便仅修复您现在拥有的错误你的每线程模式。