问题描述
我正在尝试将 EF 与 Code First 和 Web API 一起使用.在我开始序列化多对多关系之前,我没有任何问题.当我尝试执行下面的 web api 方法时,我收到以下错误消息:
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();
}
}
我收到以下错误:
'System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D'带有数据合同名称'Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D:'不是预期的.考虑使用 DataContractResolver 或添加任何已知类型列表中静态未知的类型 - 例如,通过使用KnownTypeAttribute 属性或将它们添加到传递给 DataContractSerializer 的已知类型列表.
我已经阅读了一些 SO 文章(文章 1, 文章 2) 修复是添加以下内容属性:
I have read some SO articles (article 1, article 2) that the fix is to add the following attribute:
[数据契约 (IsReference=true)]
但这没有任何效果.同样使用 [IgnoreDataMember] 没有效果.似乎可行的唯一选项是将 Configuration.ProxyCreationEnabled 设置为 false.这是我唯一的选择吗?我错过了什么吗?
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?
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 对象.
It is a runtime EF Generated version of a proxy to what would normally be considered a POCO object.
Entity Framework 创建此对象是因为它跟踪对象何时更改,因此当您调用 .SaveChanges()
时,它可以优化要执行的操作.这样做的缺点是您实际上并未使用您定义的特定对象,因此数据契约和框架 (Json.net) 无法像使用原始 POCO 对象那样使用它们.
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.
要防止 EF 返回此对象,您有两种选择 (ATM):
To Prevent EF from returning this object you have two choices (ATM):
DbContext.Configuration.ProxyCreationEnabled = false;
这将完全禁止为特定 DbContext 的每个查询创建代理对象.(这不会影响 ObjectContext 中的缓存对象).
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).
其次,使用 EntityFramework 5.0+ 和 AsNoTracking()(ProxyCreationEnabled 在 EF 5.0 中仍然可用)
Secondly, use EntityFramework 5.0+ with AsNoTracking()(ProxyCreationEnabled is still available in EF 5.0 as well)
你也应该能够
DbContext.Persons.AsNoTracking().FirstOrDefault();
或
DbContext.Persons.
.Include(i => i.Parents)
.AsNoTracking()
.FirstOrDefault();
不是全局禁用 DbContext 的代理创建,这只会在每次查询时将其关闭.(这个DOES会影响ObjectContext中的缓存对象,它没有被缓存)
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)
这篇关于具有一对多关系的实体框架对象的序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!