小编典典

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

c#

我试图将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();
        }
}

我收到以下错误:

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

我读过一些SO文章(第1条第2条),解决方法是添加以下属性:

[DataContract(IsReference = true)]

但这没有效果。同样使用[IgnoreDataMember]无效。似乎起作用的唯一选项是将Configuration.ProxyCreationEnabled设置为false。这是我唯一的选择吗?我想念什么吗?

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

阅读 254

收藏
2020-05-19

共1个答案

小编典典

当您看到类似的对象时:

System.Data.Entity.DynamicProxies.Tag_FF17EDDE6893000F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D

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

实体框架之所以创建此对象,是因为它跟踪对象的更改时间,因此在调用.SaveChanges()它时可以优化操作。这样做的缺点是您实际上并未使用定义的特定对象,因此数据合约和框架(Json.net)无法像使用原始POCO对象那样使用它们。

要防止EF返回此对象,您有两种选择(ATM):

首先,尝试在DbContext上关闭Proxy对象的创建

DbContext.Configuration.ProxyCreationEnabled = false;

这将完全禁用对特定DbContext的每个查询的代理对象的创建。(这不会影响ObjectContext中的 缓存 对象)。

其次,将 EntityFramework 5.0+
AsNoTracking()一起使用 (ProxyCreationEnabled在EF 5.0中仍然可用)

您还应该能够

DbContext.Persons.AsNoTracking().FirstOrDefault();

要么

DbContext.Persons.
  .Include(i => i.Parents)
  .AsNoTracking()
  .FirstOrDefault();

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

2020-05-19