This is the second of a two part blog series on using POCO proxies in the Entity Framework 4.0. The first post described the capabilities of proxies and details on how they work. Using proxies means your types aren’t exactly as your system expects. This can pose challenges for operations such as serialization where having the right type is critical. This post demonstrates the best practices for using proxies in scenarios where serialization is involved, either through WCF DataContract serialization or binary serialization.

Lazy Loading and Serialization

Lazy loading and serialization don’t mix well, and if you aren’t careful you can end up querying for your entire database just because lazy loading is enabled. Most serializers work by accessing each property on an instance of a type. Property access triggers lazy loading, so more entities get serialized. On those entities properties are accessed, and even more entities are loaded. It’s a good practice to turn lazy loading off before you serialize an entity. You can do this by setting the LazyLoadingEnabled property on the context to false:

context.ContextOptions.LazyLoadingEnabled = false;

WCF DataContract Serialization

It’s common to find a data access layer such as the Entity Framework in use as part of a WCF service. Services can query for entities, make updates to entities, run validation or other business logic. The entities that the service uses can be entity framework proxies, but there are some things to watch out for.

In the following example, a WCF service exposes an operation method that returns a Customer type:

To clients of this service, the operation is going to return a type “Customer”. The WSDL for this service knows about the type “Customer”. Clients will thus know about the type “Customer” but will not know about proxy types and will not be using any of the proxy behaviors. This is a good thing because your clients do not have a direct line of sight to the database to do things like lazy loading. So what happens when you try to execute the service operation and it returns a “CustomerProxy” instead of a “Customer”? If you guessed “you get an exception”, you were right.

The DataContractSerializer can only serialize and deserialize known types. There are plenty of ways to specify the list of known types to a serializer, but for these services we don’t want the client to have to know about proxy types (remember, no line of sight). This means proxies should not be part of the set of known types for the serializer.

Instead what we want to happen is for the proxy instance to serialize as if it was just a plain “Customer” type and not a “CustomerProxy” type. Fortunately, there is a new .NET 4.0 feature called DataContractResolver which can help. A DataContractResolver can map one type to another one during serialization; in the case of proxies, it can help map a “CustomerProxy” type to a “Customer” type. As part of the Entity Framework in .NET 4.0, we included the ProxyDataContractResolver which is an implementation of a DataContractResolver to map proxy types to their regular POCO types.

The ProxyDataContractResolver

A DataContractResolver has two methods that map types and names during the serialization process. During serialization, .NET types are mapped to type names that are part of the serialization payload. This is done in the “TryResolveType” method. The code below includes the implementation of the ProxyDataContractResolver. The TryResolveType method determines if the entity’s type is a proxy or not, and if it is a proxy uses the non-proxy type name in the payload:

The ApplyProxyDataContractResolver

Once you have a ProxyDataContractResolver, the next step is to instruct the DataContractSerializer to use it in service operations. This can be done by defining an operation behavior attribute that you can use on your service methods. The attribute class below shows how to do this:

Serializing back to proxies

Another frequent question is how to send POCO instances on the client tier back to a service tier and have them show up as proxies. This problem is more difficult and unfortunately, doesn’t have a good solution even in .NET 4.0. When the Entity Framework creates proxies, two things happen:

1. A proxy instance is created

2. All of the collection navigation properties are set with the appropriate EntityCollection<T>

The ProxyDataContractResolver doesn’t help in this case because the method ‘ResolveName’ used in deserialization only can return a type, not an instance of a proxy. This means that the resolver can only help with step 1. One possible option is to write your own custom DataContract surrogate. This does give you the option to instantiate your own proxy types using context.CreateObject<T>(), but it also requires you to implement a fair bit of your own logic to do circular reference detection and identity resolution. If you really need a proxy instance for a non-proxy POCO entity that was sent from a client to a service, the simplest solution is to copy the values sent from the client into proxy instances you create inside your service method.

Binary Serialization

Binary serialization works by serializing the memory an instance or graph of instances is using. It does not call property getters/setters like DataContract serialization does (if DataMembers are on properties). This has both advantages and disadvantages, but for proxies the main advantage is that proxy instances are not recreated by setting properties, the memory is just rehydrated. This allows proxies to be serialized and deserialized as proxy types. With binary serialization the proxy types need to be available. To do this, you can use the CreateProxyTypes method to ensure that all proxy types are available for a given MetadataWorksapce (it checks the proxy type cache, and create the proxy types that aren’t yet there):

In Summary

Proxies can be a great way to get additional functionality in your entities simply. You have to be willing to make concessions about the accessibility of your class and properties, as well as be willing to work with ICollection<T> if you are using change tracking proxies. Serialization can still be done with proxies, but it is a bit more work. Members of the EF team are thinking about how to improve the proxy experience even more by making it more flexible and customizable, as well as having better integration with other parts of .NET. Let us know your thoughts on what kinds of capabilities you’d like to see in extensible proxies for the Entity Framework.