【问题标题】:C# CodeFirst Lazy Loading with MVVM使用 MVVM 的 C# CodeFirst 延迟加载
【发布时间】:2014-02-19 18:05:57
【问题描述】:

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

我在模型中编写了许多帮助类,它们创建 DbContext、加载对象等。我曾经通过为每个线程(在静态函数中)生成单个 DbContext 并从适当的加载函数(Person.Load() 将调用 GetDbContext)获取该引用来做到这一点。这与延迟加载一起工作得非常好。

由于每个线程使用单个 DbContext,我的代码中出现了一些错误,因此决定切换到每个工作单元单个 DbContext 的更好做法,在“使用”中加载代码' 陈述。现实世界的速度差异似乎可以忽略不计。

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

解决此问题的最佳方法是什么?当访问这些属性之一时,我可以在我的 ViewModel 中手动调用模型,但我最终会在任何地方调用模型并手动执行应该在幕后发生的事情。这也意味着事情似乎不太协调——我最终得到了分离的 POCO,而且当我最初每个线程使用一个 DbContext 时,这似乎更加混乱!数据库的规范化结构确实意味着存在大量此类关系。

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

提前感谢您的任何建议。 亚当

【问题讨论】:

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


    【解决方案1】:

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

    现在你遇到了延迟加载的问题,因为一旦你到达using 范围的末尾,你就不能再启动 SQL 请求了因为上下文已经关闭了它与数据库服务器的连接当它被丢弃时

    你所说的解决方案

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

    实际上是幕后发生的事情。每个允许延迟加载其导航属性的加载实体都与实体框架相关(即那些在运行时生成的类型的 proxy-object 继承自你的 POCO),因此它实际上包含一个已经引用了DBContext

    这意味着,如果您不手动处理您的DBContext(使用using),延迟加载仍然可用。不过,这并不能解决您的所有问题,因为您可能必须处理来自不同上下文的多个实体,而这根本不会轻松工作(例如,您可以' t 将来自 DBContext 实例 A 的一个实体添加到 DBContext 实例 B)。

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

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

    如果您要启动一个新应用程序,我会说:使用 3 层无状态应用程序,尽可能缩短 EF 上下文生命周期,停用延迟加载并在代码中随处使用分离实体。

    现在,如果您已经有很多代码,您可能有两个选择:要么根据上下文生命周期的想法重构所有代码,要么对当前代码进行少量修改,以仅修复您现在遇到的错误你的每线程上下文模式。

    【讨论】:

    • 太好了,谢谢。虽然这不是一个无意义的项目,但它还处于相当早期的阶段(在 6 个月内,数据库将变得更大)。我认为从长远来看,现在接受您的 3 层建议并花时间进行重构是值得的。我把所有东西都收集得相当松散,所以不要觉得太头疼了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 2011-02-02
    • 2019-05-27
    • 1970-01-01
    相关资源
    最近更新 更多