2012-07-10 32 views
2

如何在實體框架代碼優先代理被序列化時使用DataContractAttribute(IsReference = true)進行裝飾?當POCO具有IsReference = true時序列化EF代理屬性

在使用的DataContractSerializer與ProxyContractResolver,我得到如下:

的IsReference設置類型「System.Data.Entity.DynamicProxies.MyType_59A83378572C10D0B31B6892FB6C3E7428C4BA214322C7A77BD5E1EB19E529CA」是「假」,但對於它的父類相同的設置'My.Namespace.MyType'爲'True'。派生類型必須具有與基本類型相同的IsReference值。改變類型設置

EF代理生成器似乎並不尊重我在POCO上需要的IsReference屬性(否則由於相互引用而導致堆棧溢出)。

在這些情況下,是否有任何機制來序列化EF Proxy?怎麼樣?

+0

順便說一句。爲什麼你有代理實體?當你想序列化實體時,通常建議避免使用動態代理。 – 2012-07-10 18:44:05

+0

也許我誤解了一些東西,但我希望能夠將它們從首次加載的上下文中分離出來,將它們序列化到緩存中,然後再將它們附加到不同的上下文中。該場景緩存負載昂貴的對象圖,該對象圖也必須與正在創建的新對象相關聯,例如, 'MyNewObject obj = new MyNewObject(){ExpensiveToLoad = Cache [「ExpensiveToLoad」]}。 – 2012-07-10 19:45:37

+0

通過序列化進行分離是一種正確的方法,但它仍不能解釋爲什麼使用代理?你需要延遲加載來構建對象圖嗎? – 2012-07-10 20:58:16

回答

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中測試了它。

+0

是的,所有都標有'IsReference = true'。他們與該屬性共享一個共同的基類。我還沒有使用.NET 4.5。也許差異在於此。 – 2012-07-12 03:46:29

+0

.NET 4.0中有其他的方法嗎? – 2012-11-19 20:01:09

+0

@LeoLuis:這應該在.NET 4.0中工作。 – 2012-11-19 21:08:14

1

請注意,僅當代理類直接指定IsReference=true時,才能使用ProxyDataContractResolver()
它目前不工作,如果它在基類上完成,如上面第一條評論所述。

相關問題