Tri Q Tran
Tri Q Tran

Reputation: 5690

EF Code First - Get POCO from Proxy

Question:

Is it possible when dealing with dynamic proxy to pull out the underlying POCO when we need to serialize them?

Rationale:

I have a requirement to serialize (XML) my POCO entities using EF Code First but quickly found that DbContext creates dynamic proxy for my POCO and that makes it hard to serialize.

I have tried the following:

  1. Disable proxy creation in the DbContext and work only with pure POCO. This allows me to serialize the instances any way I like. The only catch is that navigational properties are not being tracked, therefore, I must attach all related entities manually when I want to save otherwise new entities will always be created (see code example).
  2. Implement ISerializable interface on the POCO to manually handle serialization. This is a lot of work and is not a sustainable solution.

Code example.

// Attach and update tags
foreach (var tag in entity.Tags)
{
    Context.Entry(tag).State = Context.Tags.Any(t => t.ID == tag.ID)
                                    ? EntityState.Modified
                                    : EntityState.Added;
}

// Attach and update state.
Context.Entry(entity).State = Context.Resources.Any(x => x.ID == entity.ID)
                                    ? EntityState.Modified
                                    : EntityState.Added;

As you can imagine, the complexity can get out of hand when my entity have more relationships.

Upvotes: 3

Views: 1698

Answers (1)

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364259

Is it possible when dealing with dynamic proxy to pull out the underlying POCO when we need to serialize them?

No because there is no underlying POCO - the proxy is not a wrapper around entity instance. It is entity instance directly.

You can use DataContractSerializer and ProxyDataContractResolver to serialize proxied POCOs but serializing proxied entities sounds like you are trying to serialize entities with lazy loading enabled - that can serialize much more than you expect because every property will be lazy loaded recursively until there is no single non-loaded navigation property in the whole object graph.

You must also handle circular references when using DataContractSerializer by marking your entities with [DataContract(IsReference = true)] and every serializable property with [DataMember].

The only catch is that navigational properties are not being tracked

Entities without proxy are tracked as well. The tracking is dependent on entity being attached not entity being proxied.

I must attach all related entities manually when I want to save

You must always attach deserialized entities if you want to persist them.

Upvotes: 4

Related Questions