2

プロキシしているクラスが装飾されている場合、Entity Framework Code First Proxy をシリアル化するにはどうすればよいDataContractAttribute(IsReference = true)ですか?

ProxyContractResolver で DataContractSerializer を使用すると、次のようになります。

タイプ 'System.Data.Entity.DynamicProxies.MyType_59A83378572C10D0B31B6892FB6C3E7428C4BA214322C7A77BD5E1EB19E529CA' の IsReference 設定は 'False' ですが、その親クラス 'My.Namespace.MyType' の同じ設定は 'True' です。派生型の IsReference の値は、基本型と同じでなければなりません。タイプの設定を変更する

EF Proxy Generator は、POCO で必要な IsReference 属性を尊重していないようです (そうしないと、相互参照が原因でスタック オーバーフローが発生します)。

これらの状況で EF プロキシをシリアル化するメカニズムはありますか? どのように?

4

2 に答える 2

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 でテストしました。

于 2012-07-11T21:13:40.400 に答える
1

ProxyDataContractResolver()プロキシされたクラスがIsReference=true直接指定されている場合にのみ機能することに注意してください。
上記の最初のコメントに記載されているように、基本クラスで実行された場合、現在は機能しません。

于 2013-01-25T16:55:38.060 に答える