具有一对多关系的entity framework对象的序列化
我试图用Code First和Web API来使用EF。 在进入序列化多对多关系之前,我没有任何问题。 当我尝试执行下面的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'与数据协定名称'Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D: http : //schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies '不是预期的。 考虑使用DataContractResolver,或者将未知的静态types添加到已知types的列表中 – 例如,使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知types的列表中。
我已经阅读了一些SO文章( 第1条 , 第2条 ),修正是添加以下属性:
[DataContract(IsReference = true)]
但是这没有效果。 另外使用[IgnoreDataMember]也没有效果。 似乎工作的唯一select是将Configuration.ProxyCreationEnabled设置为false。 这是我唯一的select吗? 我错过了什么吗?
示例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
它是通常被视为POCO对象的代理的运行时EF生成版本。
entity framework已经创build了这个对象,因为它跟踪对象何时改变,所以当你调用.SaveChanges()
它可以优化做什么。 这是因为你实际上并没有使用你定义的特定对象,所以数据合同和框架(Json.net)不能像原来的POCO对象那样使用它们。
为了防止EF返回这个对象,你有两个select(ATM):
首先, 请尝试closures您的DbContext上的代理对象创build 。
DbContext.Configuration.ProxyCreationEnabled = false;
这将完全禁用为特定DbContext的每个查询创build代理对象。 (这不会影响ObjectContext中的caching对象)。
其次,使用EntityFramework 5.0+和AsNoTracking() (ProxyCreationEnabled在EF 5.0中也是可用的)
你也应该能够
DbContext.Persons.AsNoTracking().FirstOrDefault();
要么
DbContext.Persons. .Include(i => i.Parents) .AsNoTracking() .FirstOrDefault();
而不是全局禁用DbContext的代理创build,这只会closures每个查询。 (这会影响ObjectContext中的caching对象,它不会被caching)
我想离开代理创build,并发现使用ProxyDataContractResolver
似乎为我解决了这个问题。 有关如何在wcf中使用它的参考,请参阅msdn ,这不完全是WebAPI,但应该让你沿着正确的道路前进。
db.Configuration.ProxyCreationEnabled = false;
将解决你的问题