Serialize EF Proxy when POCO has IsReference = true Attribute

北慕城南 提交于 2019-12-11 01:58:02

问题


How can I serialize an Entity Framework Code First Proxy when the class it is proxying is decorated with DataContractAttribute(IsReference = true)?

When using DataContractSerializer with ProxyContractResolver, I get the following:

The IsReference setting for type 'System.Data.Entity.DynamicProxies.MyType_59A83378572C10D0B31B6892FB6C3E7428C4BA214322C7A77BD5E1EB19E529CA' is 'False', but the same setting for its parent class 'My.Namespace.MyType' is 'True'. Derived types must have the same value for IsReference as the base type. Change the setting on type

It seems that the EF Proxy Generator is not respecting the IsReference attribute, which I do need on the POCO (otherwise I end up with a stack overflow due to mutual referencing).

Is there any mechanism at all to serialize an EF Proxy under these circumstances? How?


回答1:


I just did following very simple example and ProxyDataContractResolver works as expected - graph of proxied entities with cycles was correctly serialized.

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

There must be something more complicated in your model to break the functionality - are all your entities marked with DataContract(IsReference=true)?

Note: I tested it in .NET 4.5.




回答2:


Notice that using the ProxyDataContractResolver() only works if the proxied class specifies IsReference=true directly.
It does NOT currently work if it is done on a base class as noted in the first comment above.



来源:https://stackoverflow.com/questions/11418822/serialize-ef-proxy-when-poco-has-isreference-true-attribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!