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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13077328/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 01:33:21  来源:igfitidea点击:

Serialization of Entity Framework objects with One to Many Relationship

c#entity-framework.net-4.5

提问by Blake Blackwell

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:

我正在尝试将 EF 与 Code First 和 Web API 一起使用。在我开始序列化多对多关系之前,我没有任何问题。当我尝试执行下面的 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. 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.

:“System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D”数据合同名称“Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies预计不会”。考虑使用 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)]

[数据合同(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?

但这没有效果。同样使用 [IgnoreDataMember] 没有效果。似乎可行的唯一选项是将 Configuration.ProxyCreationEnabled 设置为 false。这是我唯一的选择吗?我错过了什么吗?

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; }
}

采纳答案by Erik Philips

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 proxyto what would normally be considered a POCO object.

它是通常被视为 POCO 对象的代理的运行时 EF 生成版本。

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.

实体框架创建了这个对象,因为它跟踪对象何时发生变化,因此当您调用.SaveChanges()它时可以优化要执行的操作。这样做的缺点是您实际上并未使用您定义的特定对象,因此数据协定和框架 (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. (This does not affect the cachedobject in the ObjectContext).

这将完全禁止为特定 DbContext 的每个查询创建代理对象。(这不会影响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 globallydisabling proxy creation for the DbContext, this only turns it off per query. (This DOESaffect the cachedobject in the ObjectContext, it is not cached)

这不是全局禁用 DbContext 的代理创建,而是仅在每次查询时将其关闭。(这DOES影响缓存中的ObjectContext对象,它是不缓存)

回答by Dave

I wanted to leave proxy creation inteact, and found that using the ProxyDataContractResolverseemed to resolve the issue for me. See msdnfor a reference on how to use it in wcf, which isn't exactly WebAPI, but should get you going along the right path.

我想让代理创建保持原状,发现使用ProxyDataContractResolver似乎可以解决我的问题。有关如何在 wcf 中使用它的参考,请参阅msdn,这不完全是 WebAPI,但应该可以让您走上正确的道路。