Serialization of Entity Framework objects with One to Many Relationship

.net-4.5 c# entity-framework

Question

With Code First and the Web API, I'm trying to leverage EF. Up until I start serializing Many-to-Many connections, I have no issues. I get the following problem when attempting to use the web api function below:

public class TagsController : ApiController
{

        private BlogDataContext db = new BlogDataContext();

        // GET api/Tags
        public IEnumerable<Tag> GetTags()
        {
            return db.Tags.AsEnumerable();
        }
}

I encounter the following issue:

'System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D' with data contract name 'Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

I've read in various SO posts (paragraph 1, Paragraph 2) that adding the following attribute is the solution:

[DataContract (IsReference=true)]

However, this has had little impact. Additionally, [IgnoreDataMember] has no impact. Setting Configuration is the only option that seems to be effective. false for ProxyCreationEnabled. Is this the only choice I have? Do I have anything missing?

POCO examples of objects

Tag

[DataContract(IsReference = true)]
public class Tag
{
        public Tag()
        {
            this.Blogs = new HashSet<Blog>();
        }

        [Key]
        [DataMember]
        public int Id { get; set; }

        [DataMember]
        public string Name { get; set; }

        [IgnoreDataMember]
        public virtual ICollection<Blog> Blogs { get; set; }
}

Blog

[DataContract(IsReference = true)]
public class Blog
{
    public Blog()
    {
        this.Tags = new HashSet<Tag>();
    }

    [Key]
    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string Name { get; set; }

    [IgnoreDataMember]
    public virtual ICollection<Tag> Tags { get; set; }
}
1
34
5/23/2017 12:10:03 PM

Accepted Answer

When you see a thing like:

System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D

It is a runtime EF Generated version of an object that would typically be categorized as a POCO object (proxy).

This object was generated by Entity Framework because it monitors when an item has changed so that when you call.SaveChanges() It can improve what is done. The drawback of this is that Data Contracts and Frameworks (Json.net) cannot utilize them as they would your original POCO object since you aren't truly utilizing the exact object you described.

There are two ways to stop EF from returning this object (ATM):

Initially, Try disabling the generation of proxy objects in your DbContext..

DbContext.Configuration.ProxyCreationEnabled = false;

By doing this, every query to the specified DbContext will no longer result in the creation of Proxy objects. (The cached object in the ObjectContext is unaffected by this.)

In addition, combine 5.0+ EntityFramework with AsNoTracking() (ProxyCreationEnabled is still available in EF 5.0 as well)

Ideally, you'll be able to

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

or

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

This just disables proxy generation for a specific query, as opposed to globally disabling it for the DbContext. (This affects the ObjectContext's cached object; it is not cached.)

87
5/23/2017 12:10:03 PM

Popular Answer

When I decided to forgo the automatic establishment of proxies, I discovered thatProxyDataContractResolver for me, seems to make the problem go away. Although not precisely a WebAPI, msdn provides instructions on how to use it in wcf and should get you started in the right direction.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow