Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有一对多关系的实体框架对象序列化_C#_Entity Framework_.net 4.5 - Fatal编程技术网

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

C# 具有一对多关系的实体框架对象序列化,c#,entity-framework,.net-4.5,C#,Entity Framework,.net 4.5,我正在尝试将EF与代码和Web API一起使用。在我开始序列化多对多关系之前,我没有任何问题。当我尝试执行以下web api方法时,我收到以下错误消息: public class TagsController : ApiController { private BlogDataContext db = new BlogDataContext(); // GET api/Tags public IEnumerable<Tag> Get

我正在尝试将EF与代码和Web API一起使用。在我开始序列化多对多关系之前,我没有任何问题。当我尝试执行以下web api方法时,我收到以下错误消息:

public class TagsController : ApiController
{

        private BlogDataContext db = new BlogDataContext();

        // GET api/Tags
        public IEnumerable<Tag> GetTags()
        {
            return db.Tags.AsEnumerable();
        }
}
公共类标记控制器:ApiController
{
私有BlogDataContext db=新BlogDataContext();
//获取api/标签
公共IEnumerable GetTags()
{
返回db.Tags.AsEnumerable();
}
}
我得到以下错误:

“System.Data.Entity.DynamicProxies.Tag_FF17EDDE689300F767649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D” 使用数据合同名称 “标签号为EDDE6893000F767264949692DB0CA591C699DDB73E8C2A56203ED7C7B6D:” 这是预料不到的。考虑使用DATACONTracTracever或添加任何 已知类型列表中静态未知的类型-例如, 通过使用KnownTypeAttribute属性或将其添加到 传递给DataContractSerializer的已知类型列表

我已经阅读了一些文章(,),修复方法是添加以下属性:

[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; }
}
[DataContract(IsReference=true)]
公共类标签
{
公共标签()
{
this.Blogs=new HashSet();
}
[关键]
[数据成员]
公共int Id{get;set;}
[数据成员]
公共字符串名称{get;set;}
[IgnoreDataMember]
公共虚拟ICollection博客{get;set;}
}
博客

[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; }
}
[DataContract(IsReference=true)]
公共类博客
{
公共博客()
{
this.Tags=newhashset();
}
[关键]
[数据成员]
公共int Id{get;set;}
[数据成员]
公共字符串名称{get;set;}
[IgnoreDataMember]
公共虚拟ICollection标记{get;set;}
}

当您看到以下对象时:

System.Data.Entity.DynamicProxies.Tag_FF17EDD689300F7672649A39962DB0CA591C699DDB73E8C2A56203ED7C7B6D

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

Entity Framework创建此对象是因为它跟踪对象的更改时间,因此当您调用
.SaveChanges()
时,它可以优化操作。这样做的缺点是您实际上没有使用您定义的特定对象,因此数据契约和框架(Json.net)不能像使用原始POCO对象那样使用它们

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

首先

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

其次,使用EntityFramework 5.0+和 (ProxyCreationEnabled在EF 5.0中仍然可用)

你也应该能够

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


这并不是全局禁用DbContext的代理创建,而是只在每个查询中关闭它。(这确实会影响ObjectContext中的缓存对象,它不会被缓存)

我想保留代理创建界面,并发现使用
ProxyDataContractResolver
似乎可以解决这个问题。有关如何在wcf中使用它的参考信息,wcf不完全是WebAPI,但应该会让您走上正确的道路。

我遇到了完全相同的问题,我发现唯一的解决方案就是您和Erik Philips所说的。关闭代理创建。
IgnoreDataMember
无效的原因是,问题在于代理生成,而不是
标记的
ICollection
的序列化。我也有同样的问题,您是如何解决的?当我禁用代理创建时,我无法获取父级的值,我需要它。请帮助我。问题是,为了让实体框架跟踪更改,当您向它请求一个实例时,它提供了一个包装好的实例,该实例具有用于更改跟踪的触发器。包装的实例几乎总是无法序列化。@ErikPhilips很抱歉,我无法理解解决方案,所以我不应该禁用代理创建?还是我应该?然后我应该使用dbcontext.class.AsNoTracking().FirstOrDefault()?它到底是做什么的?@Dark_Knight更新了我的答案,我希望它有你想要的细节。非常感谢!我也不得不在EF6上使用这个-你帮我省去了很多挫折@ErikPhilips如果我全局禁用ProxyCreation会有什么后果?您介意向我解释如何使用ProxyDataContractResolver来序列化poco实体吗?我找到的唯一一个例子涉及WCF,但我不知道它是如何工作的。