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

时间:2012-07-10 17:37:24

标签: entity-framework serialization ef-code-first

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

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

  

类型' System.Data.Entity.DynamicProxies.MyType_59A83378572C10D0B31B6892FB6C3E7428C4BA214322C7A77BD5E1EB19E529CA'的IsReference设置。是' False',但其父类' My.Namespace.MyType'的设置相同。是真的'。派生类型必须与IsReference具有相同的基本类型值。更改类型

上的设置

似乎EF代理生成器不遵守IsReference属性,我在POCO上需要这个属性(否则由于相互引用而导致堆栈溢出)。

在这些情况下,是否有任何机制可以序列化EF代理?怎么样?

2 个答案:

答案 0 :(得分:4)

我只是按照非常简单的示例进行操作,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; }
    }
}

模型中必须有更复杂的内容才能破坏功能 - 您的所有实体都标有DataContract(IsReference=true)吗?

注意:我在.NET 4.5中测试过它。

答案 1 :(得分:1)

请注意,只有代理类直接指定ProxyDataContractResolver()时才使用IsReference=true 如果它是在基类上完成的,它目前无效,如上面第一条评论中所述。