我应该使用实体框架4.1和MVC3启用还是禁用动态代理?

mat*_*dev 68 orm entity-framework dynamic-proxy ef-code-first entity-framework-4.1

有人可以提供一些建议或指出一些可以帮助做出这个决定的博客/文章吗?代理对我来说似乎很陌生,我对使用它们犹豫不决.我喜欢通过在我的模型中使用虚拟属性来控制延迟加载的能力,但这几乎是我能看到的所有好处.我的应用程序是一个简单的MVC Web应用程序,当实体遇到更改状态时,我不需要将任何挂钩连接到上下文中.

无论如何,这是我现在非常有限的利弊列表,让我知道如果我没有任何这个.

优点

  • 在"保存"或"更新"中,我与"Apply'Changes"无缝对接
  • 延迟加载配置非常简单.

缺点

  • 从来没有为我的实体使用代理,这是一种方法的改变,对我自己和团队成员来说似乎不舒服.
  • 调试很尴尬.
  • 如果我想要序列化/反序列化,则需要额外的代码
  • 在"保存"或"更新"时,代理必须是从上下文中检索的同一对象.

Sla*_*uma 102

如果你谈论EF中的动态代理,有两种不同的类型可以区分:

  • 延迟加载的代理
  • 代理变更跟踪

通常,更改跟踪代理也可以作为延迟加载的代理.反之则不然.这是因为更改跟踪代理的要求更高,尤其是所有属性 - 也就是标量属性 - 必须是virtual.对于延迟加载,导航属性就足够了virtual.

更改跟踪代理始终也允许利用延迟加载这一事实是DbContext具有此配置标志的主要原因:

DbContext.Configuration.LazyLoadingEnabled
Run Code Online (Sandbox Code Playgroud)

默认情况下,此标志为true.将其设置为false禁用延迟加载,即使创建了代理.如果您正在使用更改跟踪代理但不希望将这些代理用于延迟加载,这一点尤为重要.

选项 ...

DbContext.Configuration.ProxyCreationEnabled
Run Code Online (Sandbox Code Playgroud)

...完全禁用代理创建 - 用于更改跟踪和延迟加载.

如果您的实体类满足创建更改跟踪或延迟加载代理的要求,则两个标记都只有一个含义.

现在,您了解动态延迟加载代理的目的.那么,为什么要使用动态变更跟踪代理呢?

实际上,我所知道的唯一原因是性能.但这是一个非常有力的理由.将基于快照的快照跟踪与基于代理的变更跟踪进行比较,性能差异非常大 - 从我的测量结果来看,50到100的因素是现实的(取自一个方法,需要大约一小时的10000个entites,基于快照的变化跟踪和30到60秒将所有属性设置为虚拟以启用更改跟踪代理后).如果您有一些应用程序可以处理和更改许多(例如超过1000个)实体,那么这将成为一个重要因素.在Web应用程序中,您可能只对Web请求中的单个实体进行创建/更改/删除操作,这种差异并不重要.

在几乎所有情况下,如果您不想使用延迟加载代理,您可以利用eager或explicite加载来实现相同的目标.基于代理的延迟加载或基于非代理的explicite加载的性能是相同的,因为在加载导航属性时基本上发生相同的查询 - 在第一种情况下代理执行查询,在第二种情况下是您的手写代码.所以,你可以在没有延迟加载代理的情况下生活而不会损失太多.

但是如果你想要合理的性能来处理许多实体,除了EntityObject在EF 4.0中使用派生实体(不是EF 4.1中的选项,因为它在你使用时被禁止DbContext)或根本不使用实体框架时,除了更改跟踪代理之外别无选择. .

编辑(2012年5月)

与此同时,我了解到,与基于快照的跟踪相比,在某些情况下,更改跟踪代理的性能不会更快甚至更差.

由于使用更改跟踪代理时出现这些复杂情况,首选方法是默认情况下使用基于快照的更改跟踪,并且仅在需要高性能并且证明比基于快照的速度更快的情况下仔细使用代理(在执行某些测试之后)改变跟踪.


小智 15

对于使用Entity Framework 5的任何人,请务必查看性能注意事项文章.Sections 5 NoTracking Queries8 Loading Related Entities提供您做出明智决定所需的信息.干杯.