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

发布于 2024-11-30 10:08:17 字数 515 浏览 0 评论 0原文

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

不管怎样,这是我现在列出的非常有限的利弊清单,如果我的观点有误,请告诉我。

优点

  • 在“保存”或“更新”时,我可以与“应用更改”无缝连接,
  • 延迟加载配置非常简单。

缺点

  • 我的实体以前从未使用过代理,这是一个变化 对于我自己和其他团队来说,这种方法似乎让人感到不舒服 成员。
  • 调试起来很尴尬。
  • 如果我想在“保存”或“更新”上序列化/反序列化
  • ,则需要额外的代码,代理必须是从上下文中检索到的同一对象。

Could someone offer up some advice or point out some blogs/articles that could help with making this decision? The proxies seem very foreign to me and I'm hesitant to use them. I like the ability to control Lazy Loading by using virtual properties in my model, but that's pretty much all the benefits that I can see. My application is a simple MVC web application and I don't need to wire up any hooks into the context for when the entities experience a changed state.

Anyway, here's my very limited list of pros and cons right now, let me know if I'm off base with any of this.

Pros

  • On 'Save' or 'Update', I get seamless with 'Apply'Changes'
  • Lazy-Loading configuration is very easy.

Cons

  • Never used proxies before for my entities, this is a change in
    approach that just seems uncomfortable for myself and fellow team
    members.
  • Awkward to debug.
  • Requires extra code if I want serialize/de-serialize
  • On 'Save' or 'Update', the proxy must be the same object that was retrieved from the context.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

卸妝后依然美 2024-12-07 10:08:17

如果您谈论 EF 中的动态代理,则有两种不同的类型需要区分:

  • 用于延迟加载的代理
  • 用于更改跟踪的代理

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

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

DbContext.Configuration.LazyLoadingEnabled

此标志默认为 true。将其设置为 false 会禁用延迟加载,即使创建了代理也是如此。如果您正在使用更改跟踪代理但又不想使用这些代理进行延迟加载,这一点尤其重要。

选项 ...

DbContext.Configuration.ProxyCreationEnabled

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

仅当您的实体类满足创建更改跟踪或延迟加载代理的要求时,这两个标志才有意义。

现在,您知道动态延迟加载代理的用途了。那么,为什么要使用动态变更跟踪代理呢?

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

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

但是,如果您希望以合理的性能来处理许多实体,则没有其他选择可以更改跟踪代理 - 除了在 EF 4.0 中使用 EntityObject 派生实体(EF 4.1 中不是一个选项,因为当您使用DbContext)或根本不使用实体框架。

编辑(2012 年 5 月)

与此同时,我了解到在某些情况下 更改跟踪代理的性能并不更快,甚至更差。

由于使用更改跟踪代理时存在这些复杂性,首选方法是默认使用基于快照的更改跟踪,并且仅在需要高性能并且被证明比基于快照更快的情况下才谨慎使用代理(在进行一些测试后)变更跟踪。

If you talk about dynamic proxies in EF there are two different types to distinguish:

  • Proxies for lazy loading
  • Proxies for change tracking

Usually a change tracking proxy also can serve as a proxy for lazy loading. The reverse is not true. This is because the requirements for change tracking proxies are higher, especially all properties - also the scalar properties - must be virtual. For lazy loading it is enough that the navigation properties are virtual.

The fact that a change tracking proxy always also allows to leverage lazy loading is the main reason why the DbContext has this configuration flag:

DbContext.Configuration.LazyLoadingEnabled

This flag is true by default. Setting it to false disables lazy loading even if proxies are created. This is especially important if you are working with change tracking proxies but don't want to use those proxies for lazy loading as well.

The option ...

DbContext.Configuration.ProxyCreationEnabled

... disables proxy creation completely - for change tracking and lazy loading as well.

Both flags only have a meaning at all if your entity classes meet the requirements for creating either change tracking or lazy loading proxies.

Now, you know the purpose of dynamic lazy loading proxies. So, why should one use dynamic change tracking proxies?

Actually the only reason I am aware of is performance. But this is a very strong reason. Comparing snapshot based change tracking with proxy based change tracking the performance difference is huge - from my measurements a factor of 50 to 100 is realistic (taken from a method which needed around one hour for 10000 entites with snapshot based change tracking and 30 to 60 seconds after making all properties virtual to enable change tracking proxies). This is getting an important factor if you have some application which processes and changes many (say more than 1000) entities. In a web application where you possibly only have Create/Change/Delete operations on single entities in a web request this difference doesn't matter so much.

In almost all situations you can leverage eager or explicite loading to achieve the same goal if you don't want to work with lazy loading proxies. The performance for proxy based lazy loading or non-proxy based explicite loading is the same because basically the same query happens when navigation properties are loaded - in the first case the proxy does the query, in the second case your hand-written code. So, you can live without lazy loading proxies without losing to much.

But if you want reasonable performance to process many, many entities there is no alternative to change tracking proxies - aside from using EntityObject derived entities in EF 4.0 (not an option in EF 4.1 because it's forbidden when you use DbContext) or not using Entity Framework at all.

Edit (May 2012)

In the meantime I have learned that there are situations where change tracking proxies are not faster or even worse in performance compared to snapshot based tracking.

Due to these complications when using change tracking proxies, the prefered way is to use snapshot based change tracking by default and use proxies carefully (after doing some tests) only in situations where high performance is required and where they prove to be faster than snapshot based change tracking.

不及他 2024-12-07 10:08:17

对于使用 Entity Framework 5 的任何人,请务必查看性能注意事项一文。 第 5 节 NoTracking 查询8 加载相关实体 提供您做出明智决策所需的信息。干杯。

For anyone using Entity Framework 5, be sure to check out the Performance Considerations article. Sections 5 NoTracking Queries and 8 Loading Related Entities offers the info you need to make an informed decision. Cheers.

你曾走过我的故事 2024-12-07 10:08:17

我建议不要使用代理。动态代理创建会破坏依赖于运行时类型检查的组件或使其变得复杂。

例如,自动映射器将在运行时抛出类型不匹配/意外类型错误,因为您的实体将在运行时动态生成代理类型,而不是配置自动映射时传入的类型。

I would suggest NOT using proxies. Dynamic proxy creation breaks or creates complications for components which are dependent on runtime type checking.

Automapper, for instance, will throw a type mismatch / unexpected type error during runtime as your entities will have dynamically generated proxy types during runtime, and not the types you passed in when configuring automapping.

玻璃人 2024-12-07 10:08:17

尽管动态代理有一些不错的功能,但实际上它们可能会产生许多奇怪且晦涩的错误。

例如,在我的一个类中保留了一个实体的私有变量(它正在实现批处理),我循环遍历几百万条记录,批量处理和插入它们,每 n 条记录重新创建数据上下文清理内存。尽管我从未使用过私有变量,但 EF 会将其链接到我的新对象(通过导航属性有一个引用),即使我只设置了引用 Id。

这导致所有对象在进程运行的整个过程中都保留在内存中。我必须使用 AsNoTracking 并禁用代理,以便进程按预期工作,并使内存和性能恢复到正常水平。请记住,代理还引用创建它们的上下文,这可以在内存中保留巨大的实体图,几乎不可能对其进行调试

因此,我认为您应该全局禁用代理并在小的且包含的片段中启用它们代码。调试此类问题是非常危险且不可能的,特别是当您有大型团队编码时。

更改跟踪很好,它可能证明在某些地方使用是合理的。
除非您知道自己在做什么,否则延迟加载可能会成为性能和序列化方面的一个巨大问题。我始终喜欢急切或显式加载。

Although dynamic proxies have a few nice features, in reality they can create a lot of strange and obscure bugs.

For example a kept a private variable of an entity in one of my classes (it was implementing a batch process) and I was looping through a few millions of records, processing and inserting them in batches, recreating the data context every n-records to clean the memory. Although I NEVER used the private variable, EF was linking it to my new objects (there was a reference through a navigation property) even though I was only setting the reference Id.

This caused all the objects to remain in memory for the entire time the process was running. I had to use AsNoTracking and disable proxies in order for the process to work as expected and memory and performance to return to normal levels. Keep in mind that proxies also reference the context that created them and this can keep in memory huge graphs of entities, it is almost impossible to debug it

So, I believe that you should globally disable the proxies and enable them in small and contained pieces of code. It is very dangerous and impossible to debug such issues expecially when you have large teams coding.

The change tracking is nice, it might justify the usage in some places.
The lazy loading can be a huge problem in performance and serialization unless you know what you are doing. I prefer eager or explicit loading at all times.

韶华倾负 2024-12-07 10:08:17

使用自动映射器 4.2.1。新版本没有DynamicMap

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

Use Automapper 4.2.1. New version is not having DynamicMap

var parents = parentsRepo.GetAll().ToList();
Mapper.CreateMap<Parent,ParentDto>();
var parentsDto = Mapper.DynamicMap<List<ParentDto>>(parents);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文