Entity framework 当POCO具有IsReference=true属性时序列化EF代理

Entity framework 当POCO具有IsReference=true属性时序列化EF代理,entity-framework,serialization,ef-code-first,Entity Framework,Serialization,Ef Code First,当实体框架代码代理的类使用DataContractAttribute(IsReference=true)修饰时,如何序列化实体框架代码优先代理 将DataContractSerializer与ProxyContractResolver一起使用时,我得到以下结果: 类型“System.Data.Entity.DynamicProxies.MyType_59A83378572C10D0B31B6892FB6C3E7428C4BA214322C7A77BD5E1EB19E529CA”的IsRefere

当实体框架代码代理的类使用DataContractAttribute(IsReference=true)修饰时,如何序列化实体框架代码优先代理

将DataContractSerializer与ProxyContractResolver一起使用时,我得到以下结果:

类型“System.Data.Entity.DynamicProxies.MyType_59A83378572C10D0B31B6892FB6C3E7428C4BA214322C7A77BD5E1EB19E529CA”的IsReference设置为“False”,但其父类“My.Namespace.MyType”的相同设置为“True”。派生类型的IsReference值必须与基类型的IsReference值相同。更改类型的设置

EF代理生成器似乎没有考虑IsReference属性,我在POCO上确实需要IsReference属性(否则,由于相互引用,我最终会导致堆栈溢出)


在这种情况下,是否有任何机制可以序列化EF代理?如何操作?

我只是做了以下非常简单的示例,并且
ProxyDataContractResolver
按预期工作-具有循环的代理实体的图形已正确序列化

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Objects;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;

namespace CFSerialization
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var context = new Context())
            {
                context.Database.Delete();
                context.Database.CreateIfNotExists();

                context.Masters.Add(new Master
                    {
                        Name = "abc",
                        Details = new List<Detail>
                            {
                                new Detail { Name = "a" },
                                new Detail { Name = "b" },
                                new Detail { Name = "c" }
                            }
                    });
                context.SaveChanges();
            }

            using (var context = new Context())
            {
                // This will get proxied Master
                var master = context.Masters.First();

                var serializer = new DataContractSerializer(typeof(Master), new DataContractSerializerSettings()
                    {
                        DataContractResolver = new ProxyDataContractResolver()
                    });

                using (var stream = new MemoryStream())
                {
                    // This will also lazy load all details
                    serializer.WriteObject(stream, master);
                    stream.Seek(0, SeekOrigin.Begin);
                    var newMaster = (Master)serializer.ReadObject(stream);
                }
            }
        }
    }

    [DataContract(IsReference=true)]
    public class Master
    {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public virtual ICollection<Detail> Details { get; set; }
    }

    [DataContract(IsReference=true)]
    public class Detail 
    {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public virtual Master Master { get; set; }
    }

    public class Context : DbContext
    {
        public DbSet<Master> Masters { get; set; }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Data.Entity;
使用System.Data.Object;
使用System.IO;
使用System.Linq;
使用System.Runtime.Serialization;
命名空间序列化
{
班级计划
{
静态void Main(字符串[]参数)
{
使用(var context=new context())
{
context.Database.Delete();
context.Database.CreateIfNotExists();
context.Masters.Add(新Master)
{
Name=“abc”,
详细信息=新列表
{
新详细信息{Name=“a”},
新的详细信息{Name=“b”},
新详细信息{Name=“c”}
}
});
SaveChanges();
}
使用(var context=new context())
{
//这将得到代理主机
var master=context.Masters.First();
var serializer=new DataContractSerializer(typeof(Master),new DataContractSerializerSettings()
{
DataContractResolver=新的ProxyDataContractResolver()
});
使用(var stream=new MemoryStream())
{
//这也将延迟加载所有详细信息
serializer.WriteObject(流,主);
stream.Seek(0,SeekOrigin.Begin);
var newMaster=(Master)serializer.ReadObject(stream);
}
}
}
}
[DataContract(IsReference=true)]
公共班主任
{
[数据成员]
公共int Id{get;set;}
[数据成员]
公共字符串名称{get;set;}
[数据成员]
公共虚拟ICollection详细信息{get;set;}
}
[DataContract(IsReference=true)]
公共类详细信息
{
[数据成员]
公共int Id{get;set;}
[数据成员]
公共字符串名称{get;set;}
[数据成员]
公共虚拟主机{get;set;}
}
公共类上下文:DbContext
{
公共数据库集主程序{get;set;}
}
}
您的模型中必须有更复杂的东西来破坏功能-您的所有实体是否都标记有
DataContract(IsReference=true)


注意:我在.NET 4.5中对其进行了测试。

请注意,仅当代理类直接指定
IsReference=true
时,使用
ProxyDataContractResolver()
才有效。

如果它是在上面第一条评论中提到的基类上完成的,那么它目前不起作用。

Btw。为什么有代理实体?当您想要序列化实体时,通常建议避免使用动态代理。也许我误解了什么,但我希望我可以将它们从第一次加载它们的上下文中分离出来,将它们序列化到缓存,然后将它们附加到不同的上下文。场景是缓存一个加载成本很高的对象图,该对象图也必须与正在创建的新对象关联,例如
MyNewObject obj=newmynewobject(){ExpensiveToLoad=Cache[“ExpensiveToLoad”]}
。通过序列化分离是一种正确的方法,但它仍然没有解释为什么要使用代理?是否需要延迟加载来构建对象图?是的,因为存在此问题:是,所有对象都标记为
IsReference=true
。它们与该属性共享一个公共基类。我还没有使用.NET4.5。也许区别就在这里。在.NET 4.0中有其他方法吗?但不是这一部分,新的DataContractSerializerSettings(){DataContractResolver=new ProxyDataContractResolver()});无论如何,我找到了另一种方法