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 serial开发者_JAVA技巧ize/de-serialize
- On 'Save' or 'Update', the proxy must be the same object that was retrieved from the context.
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.
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.
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.
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.
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);
精彩评论