实体框架与序列化对象的一个一对多关系 [英] Serialization of Entity Framework objects with One to Many Relationship
问题描述
我试图使用带有code首先和Web API EF。我没有任何问题,直到我进入序列许多一对多的关系。当我尝试执行以下Web API方法下面我收到以下错误信息:
公共类TagsController:ApiController
{ 私人BlogDataContext DB =新BlogDataContext(); //获取API /标签
公共IEnumerable的<标记和GT; GetTags()
{
返回db.Tags.AsEnumerable();
}
}
我收到以下错误:
'System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D'
数据合同名称
'Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies'
预计不会。考虑使用DataContractResolver或添加任何
类型不是静态已知的已知类型的列表 - 例如,
通过使用KnownTypeAttribute属性或通过将其添加到
已知类型的列表传递给DataContractSerializer的
块引用>我看过一些文章SO(<一个href=\"http://stackoverflow.com/questions/11315311/using-navigation-properties-in-entity-framework-$c$c-first\">article 1 ,第2条)的修复是添加以下属性:
[DataContract(IsReference = TRUE)]
块引用>但这是没有效果的。还使用[IgnoreDataMember]不具有效果。这似乎工作的唯一的选择就是Configuration.ProxyCreationEnabled设置为false。这是我唯一的选择吗?我缺少的东西吗?
样品POCO对象:的
代码
[DataContract(IsReference =真)]
公共类标签
{
公共标签()
{
this.Blogs =新的HashSet&LT;博客&GT;();
} [键]
[数据成员]
公众诠释标识{搞定;组; } [数据成员]
公共字符串名称{;组; } [IgnoreDataMember]
公共虚拟的ICollection&LT;博客&GT;博客{搞定;组; }
}博客
[DataContract(IsReference =真)]
公共类博客
{
公共博客()
{
this.Tags =新的HashSet&LT;吊牌及GT;();
} [键]
[数据成员]
公众诠释标识{搞定;组; } [数据成员]
公共字符串名称{;组; } [IgnoreDataMember]
公共虚拟的ICollection&LT;标记和GT;标签{搞定;组; }
}
解决方案当你看到这样一个对象:
System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D
块引用>这是一个的代理运行时产生的EF版本的什么通常会被认为是一个POCO对象。
因为它跟踪时的对象发生了变化,所以当你调用.SaveChanges()
它可以优化做什么实体框架创建该对象。这样做的缺陷是你没有实际使用您定义的特定对象,因此数据合同和框架(Json.net)不能用他们,因为他们将原来的POCO对象。
这回该对象prevent EF你有两个选择(ATM):
首先,尝试在您的DbContext 关闭代理对象的创建。
DbContext.Configuration.ProxyCreationEnabled = FALSE;
这将完全禁用创建的代理对象为每个查询到具体的DbContext。 (这不影响的缓存的在ObjectContext的对象)。
其次,使用的EntityFramework 5.0 + 使用 AsNoTracking()
(ProxyCreationEnabled仍然可用在EF 5.0为好)您也应该能够
DbContext.Persons.AsNoTracking()FirstOrDefault()。
或
DbContext.Persons。
.INCLUDE(I =&GT; i.Parents)
.AsNoTracking()
.FirstOrDefault();代替的全球的禁用代理创建为的DbContext,这只是将其关闭每次查询。 (这的 DOES 的影响的缓存的对象ObjectContext中,它是不缓存)
I am attempting to use EF with Code First and the Web API. I don't have any problems until I get into serializing Many-to-Many relationships. When I attempt to execute the following web api method below I get the following error message:
public class TagsController : ApiController { private BlogDataContext db = new BlogDataContext(); // GET api/Tags public IEnumerable<Tag> GetTags() { return db.Tags.AsEnumerable(); } }
I get the following error:
'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 have read some SO articles (article 1, article 2) that the fix is to add the following attribute:
[DataContract (IsReference=true)]
but this has had no effect. Also using [IgnoreDataMember] does not have an effect. The only option that does seem to work is to set Configuration.ProxyCreationEnabled to false. Is this my only option? Am I missing something?
Sample POCO 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; } }
解决方案When you see an object like:
System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D
It is a runtime EF Generated version of a proxy to what would normally be considered a POCO object.
Entity Framework has created this object because it tracks when the objects has changed so when you call
.SaveChanges()
it can optimize what to do. The downfall of this is that you aren't actually using the specific object you defined, thus Data Contracts and Frameworks (Json.net) cannot use them as they would your original POCO object.To Prevent EF from returning this object you have two choices (ATM):
First, Try turning off Proxy object creation on your DbContext.
DbContext.Configuration.ProxyCreationEnabled = false;
This will completely disable the create of Proxy objects for every query to the specific DbContext. (This does not affect the cached object in the ObjectContext).
Secondly, use EntityFramework 5.0+ with AsNoTracking() (ProxyCreationEnabled is still available in EF 5.0 as well)
You should also be able to
DbContext.Persons.AsNoTracking().FirstOrDefault();
or
DbContext.Persons. .Include(i => i.Parents) .AsNoTracking() .FirstOrDefault();
Instead of globally disabling proxy creation for the DbContext, this only turns it off per query. (This DOES affect the cached object in the ObjectContext, it is not cached)
这篇关于实体框架与序列化对象的一个一对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!