Serializable Classes and Dynamic Proxies in Ef - How

How to prevent Json.NET from using the Entity Framework proxy type name?

You can do two things:

  • disabling tracking proxies, by setting ProxyCreationEnabled to false. You can find this property in your context's Configuration property. If you use a context for a single GetXxx method, you can do it without interfering other context instanced.

  • using the AsNoTracking() extension method when you recover your entity, like this:

    MyContext.MyTable.AsNoTracking(). // rest of the query here

This indicates that you don't want a tracking proxy for your entity, so you'll get the entity class. This has no interference with the afore mentioned configuration.

Should I enable or disable dynamic proxies with entity framework 4.1 and MVC3?

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.

Serialization of Entity Framework objects with One to Many Relationship

When you see an object like:

System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D

It is a runtime EF Generated version of a proxy to what would normally be considered a POCO object.

Entity Framework has created this object because it tracks when the objects has changed so when you call .SaveChanges() it can optimize what to do. The downfall of this is that you aren't actually using the specific object you defined, thus Data Contracts and Frameworks (Json.net) cannot use them as they would your original POCO object.

To Prevent EF from returning this object you have two choices (ATM):

First, Try turning off Proxy object creation on your DbContext.

DbContext.Configuration.ProxyCreationEnabled = false;

This will completely disable the create of Proxy objects for every query to the specific DbContext. (This does not affect the cached object in the ObjectContext).

Secondly, use EntityFramework 5.0+ with AsNoTracking()
(ProxyCreationEnabled is still available in EF 5.0 as well)

You should also be able to

DbContext.Persons.AsNoTracking().FirstOrDefault();

or

DbContext.Persons.
.Include(i => i.Parents)
.AsNoTracking()
.FirstOrDefault();

Instead of globally disabling proxy creation for the DbContext, this only turns it off per query. (This DOES affect the cached object in the ObjectContext, it is not cached)

How can I convert a dynamic proxy into a POCO?

This is a known issue

We fixed an issue in ScriptIgnoreAttribute, which was not being propagated to derived classes. Since POCO proxy types are created by deriving from the POCO class provided by the user, the JavaScriptSerializer wasn't able to see the [ScriptIgnore] attributes you have in your repro.

The fix won't be included in the next preview release of .NET 4.5.

(so presumably you have to wait for a following preview release or the final release)

http://connect.microsoft.com/VisualStudio/feedback/details/723060/ef-4-2-code-first-property-attributes-not-honoured

that is fixed in .NET 4.5

From the comments on that issue, it looks like you can work around by using NonSerializedAttribute instead of ScriptIgnoreAttribute if you are using the current version of JSON.Net



Related Topics



Leave a reply



Submit