具有一对多关系的实体框架对象的序列化 [英] Serialization of Entity Framework objects with One to Many Relationship

查看:21
本文介绍了具有一对多关系的实体框架对象的序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 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:

'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 文章(文章 1, 文章 2) 修复是添加以下内容属性:

I have read some SO articles (article 1, article 2) that the fix is to add the following attribute:

[数据契约 (IsReference=true)]

[DataContract (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

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 上的代理对象创建.

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)

这篇关于具有一对多关系的实体框架对象的序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆