我应该启用还是禁用dynamic代理与entity framework4.1和MVC3?

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

无论如何,这里是我非常有限的利弊名单,让我知道,如果我与任何这样的基础。

优点

  • 在“保存”或“更新”上,我可以通过“应用”更改
  • 延迟加载configuration非常简单。

缺点

  • 以前从未使用过代理服务器,这是对自己和团队成员看起来不舒服的方法的改变。
  • 尴尬的debugging。
  • 如果我想序列化/反序列化,需要额外的代码
  • 在“保存”或“更新”上,代理必须是从上下文中检索的同一个对象。

如果您在EF中讨论dynamic代理,有两种不同的types可以区分:

  • 懒惰加载的代理
  • 更改跟踪的代理

通常,更改跟踪代理也可以作为延迟加载的代理。 相反是不正确的。 这是因为更改跟踪代理的要求更高,尤其是所有属性(也就是标量属性)都必须是virtual 。 对于延迟加载,导航属性是virtual就足够了。

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

 DbContext.Configuration.LazyLoadingEnabled 

这个标志默认是真的。 将其设置为false即使代理已创build,也会禁用延迟加载。 如果您正在使用更改跟踪代理,但不希望将这些代理也用于延迟加载,这一点尤其重要。

选项 …

 DbContext.Configuration.ProxyCreationEnabled 

…完全禁用代理创build – 也用于更改跟踪和延迟加载。

如果您的实体类满足创build更改跟踪或延迟加载代理的要求,那么这两个标志只具有含义。

现在,你知道dynamic延迟加载代理的目的。 那么,为什么要使用dynamic变化跟踪代理呢?

其实我知道的唯一原因就是performance 。 但这是一个非常强大的原因。 将基于快照的变更跟踪与基于代理的变更追踪相比较,性能差异是巨大的 – 从我的测量结果来看,50到100的因子是现实的(从一个需要大约1小时的方法需要10000个实例,基于快照的变更跟踪和30到60秒将所有属性虚拟为启用更改跟踪代理后)。 如果你有一些应用程序处理和改变很多(比如超过1000个)实体,这就变得非常重要。 在Web应用程序中,您可能只需在Web请求中对单个实体进行创build/更改/删除操作,但这种差异并不重要。

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

但是如果你想要合理的性能来处理很多很多的实体,除了在EF 4.0中使用EntityObject派生实体(不是EF 4.1中的一个选项,因为它在使用DbContext时是被禁止的),还是不使用entity framework在所有。

编辑(2012年5月)

与此同时,我了解到,与基于快照的跟踪相比,有些情况下更改跟踪代理的性能不会更快或更差。

由于使用变更跟踪代理时出现这些复杂情况,首选的方法是默认使用基于快照的更改跟踪,并且仅在需要高性能和certificate速度快于基于快照的情况下,仔细使用代理(在进行一些testing之后)改变跟踪。

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

我会build议不要使用代理。 dynamic代理创build中断或为依赖于运行时types检查的组件造成复杂性。

例如,Automapper会在运行时引发types不匹配/意外types的错误,因为实体在运行时会有dynamic生成的代理types,而不是configuration自动映射时传入的types。

尽pipedynamic代理具有一些很好的function,但实际上它们可能会造成很多奇怪而晦涩的bug。

例如,一个实体的私有variables保存在我的一个类中(它正在实现一个批处理过程),并且循环了几百万条logging,处理并批量插入它们,每个nlogging重新创build数据上下文清理内存。 虽然我从来没有使用私有variables,EF是链接到我的新对象(有一个通过导航属性的引用),即使我只是设置参考ID。

这导致所有对象在整个运行过程中都保留在内存中。 我不得不使用AsNoTracking并禁用代理,以使进程按预期工作,内存和性能恢复到正常水平。 请记住,代理也参考创build它们的上下文,这可以在内存中保存巨大的实体graphics,几乎不可能debugging它

所以,我相信你应该全局禁用代理,并在小代码中包含代码。 当你有大型的团队编码时,debugging这些问题是非常危险的,也是不可能的。

更改跟踪是很好的,这可能certificate某些地方的使用。 除非你知道你在做什么,否则懒惰的加载可能是性能和序列化中的一个大问题。 我总是喜欢急切或明确的加载。

使用Automapper 4.2.1。 新版本没有DynamicMap

 var parents = parentsRepo.GetAll().ToList(); Mapper.CreateMap<Parent,ParentDto>(); var parentsDto = Mapper.DynamicMap<List<ParentDto>>(parents);