简体   繁体   English

具有一对多关系的实体框架对象的序列化

[英]Serialization of Entity Framework objects with One to Many Relationship

I am attempting to use EF with Code First and the Web API. 我试图将EF与Code First和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: 当我尝试执行下面的以下Web api方法时,出现以下错误消息:

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. :“System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D”数据合同名称“Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies预计不会”。 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. 考虑使用DataContractResolver或将任何静态未知的类型添加到已知类型的列表中-例如,通过使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型的列表中。

I have read some SO articles ( article 1 , article 2 ) that the fix is to add the following attribute: 我读过一些SO文章( 第1条第2条 ),解决方法是添加以下属性:

[DataContract (IsReference=true)] [DataContract(IsReference = true)]

but this has had no effect. 但这没有效果。 Also using [IgnoreDataMember] does not have an effect. 同样使用[IgnoreDataMember]无效。 The only option that does seem to work is to set Configuration.ProxyCreationEnabled to false. 似乎起作用的唯一选项是将Configuration.ProxyCreationEnabled设置为false。 Is this my only option? 这是我唯一的选择吗? Am I missing something? 我想念什么吗?

Sample POCO objects: 样本POCO对象:

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 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. 它是运行时由EF生成的代理版本,通常称为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. 实体框架创建了此对象,因为它跟踪对象的更改时间,因此,当您调用.SaveChanges()它可以优化操作。 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. 这样做的缺点是您实际上并未使用定义的特定对象,因此数据合约和框架(Json.net)无法像使用原始POCO对象那样使用它们。

To Prevent EF from returning this object you have two choices (ATM): 要防止EF返回此对象,您有两种选择(ATM):

First, Try turning off Proxy object creation on your DbContext . 首先, 尝试在DbContext上关闭Proxy对象的创建

DbContext.Configuration.ProxyCreationEnabled = false;

This will completely disable the create of Proxy objects for every query to the specific DbContext. 这将完全禁用对特定DbContext的每个查询的代理对象的创建。 (This does not affect the cached object in the ObjectContext). (这不会影响ObjectContext中的缓存对象)。

Secondly, use EntityFramework 5.0+ with AsNoTracking() (ProxyCreationEnabled is still available in EF 5.0 as well) 其次,将EntityFramework 5.0+AsNoTracking()一起使用 (ProxyCreationEnabled在EF 5.0中仍然可用)

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. 不会全局禁用DbContext的代理创建,而是仅在每次查询时将其关闭。 (This DOES affect the cached object in the ObjectContext, it is not cached) (这确实会影响ObjectContext中的缓存对象,但不会缓存)

I wanted to leave proxy creation inteact, and found that using the ProxyDataContractResolver seemed to resolve the issue for me. 我想保持代理创建的完整性,并发现使用ProxyDataContractResolver似乎可以解决此问题。 See msdn for a reference on how to use it in wcf, which isn't exactly WebAPI, but should get you going along the right path. 请参阅msdn ,以获取有关如何在wcf中使用它的参考,它不是完全WebAPI,但应该使您走上正确的道路。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM