c# – 一对多关系的实体框架对象的序列化

我试图使用EF与Code First和Web API。我没有任何问题,直到我开始序列化多对多关系。当我尝试执行以下web api方法下面,我得到以下错误信息:

public class TagsController : ApiController
{

        private BlogDataContext db = new BlogDataContext();

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

我得到以下错误:

‘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.

我已经阅读一些SO文章(article 1article 2),修复是添加以下属性:

[DataContract (IsReference=true)]

但这没有效果。也使用[IgnoreDataMember]没有效果。看起来工作的唯一选项是将Configuration.ProxyCreationEnabled设置为false。这是我唯一的选择吗?我缺少什么?

示例POCO对象:

标签

[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; }
}

博客

[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; }
}
最佳答案
当你看到一个对象,如:

System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D

它是一个运行时EF生成的代理的版本,通常被认为是一个POCO对象。

Entity Framework创建了此对象,因为它跟踪对象何时更改,所以当调用.SaveChanges()时,它可以优化要做什么。这是因为你实际上没有使用你定义的特定对象,因此数据契约和框架(Json.net)不能像你原来的POCO对象一样使用它们。

为了防止EF返回这个对象,你有两个选择(ATM):

首先,Try turning off Proxy object creation on your DbContext

DbContext.Configuration.ProxyCreationEnabled = false;

这将完全禁用针对特定DbContext的每个查询创建Proxy对象。 (这不影响ObjectContext中的缓存对象)。

其次,使用EntityFramework 5.0与AsNoTracking()
(ProxyCreationEnabled在EF 5.0中仍然可用)

你也应该能够

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

要么

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

不是全局禁用DbContext的代理创建,这只会关闭每个查询。 (这个DOES影响ObjectContext中的缓存对象,它不被缓存)

转载注明原文:c# – 一对多关系的实体框架对象的序列化 - 代码日志