2013-02-08 76 views
17

我有一個類,我想保留元數據 - 有幾個交互場景,所以meta允許我爲不同的交互類型保留不同的元。我可以在EF實體中嵌入對象嗎(保存時序列化,訪問時反序列化)?

class Feed() 
{ 
    Guid FeedId { get; set; } 
    ObjectMetaDictionary Meta { get; set; } 
} 

我想要EF將此ObjectMetaDictionary序列化並將其作爲字符串/ VarChar存儲在數據庫中。當我檢索一條記錄時,我想將它作爲ObjectMetaDictionary反序列化。

EF支持嗎?我該怎麼做?

我首先使用實體​​框架代碼。

已解答:我在下面提供了一個答案,解決了我的問題。只要SO允許,我會盡快接受這個答案。

+0

更新:我開始寫這個問題後使用MongoDB的郵件。對Mongo來說,這個問題甚至都不重要,因爲它很容易做到。我在使用SQL時喜歡使用EF,但我寧願在一週中的任何一天使用Mongo,並且根據14年的經驗,我會說mongo在任何一天都會對web/apps有更好的表現。 – kingdango 2013-12-19 13:39:11

回答

22

顯然這其實很簡單。我能夠得到它的工作得益於這個以前的SO answer的一些幫助。

流利的配置OnModelCreating允許我們告訴EF如何使用作爲序列化到數據庫的值屬性並再次返回。

這裏是我的解決方案:

public class Feed 
{ 
    public virtual Guid FeedId { get; set; } 

    public virtual FeedMetaData Meta { get; set; } 

    public virtual string Title { get; set; } 
    public virtual string Description { get; set; } 

} 

public class FeedMetaData 
{ 
    public Dictionary<string, string> Data { get; set; } 

    public string Serialized 
    { 
     get { return JsonConvert.SerializeObject(Data); } 
     set 
     { 
      if(string.IsNullOrEmpty(value)) return; 

      var metaData = JsonConvert.DeserializeObject<Dictionary<string, string>>(value); 

      Data = metaData ?? new Dictionary<string, string>(); 
     } 
    } 

    // addl code removed... 
} 

public class FeedsDbContext : DbContext 
{ 
    public DbSet<Feed> Feeds { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.ComplexType<FeedMetaData>() 
        .Property(p => p.Serialized) 
        .HasColumnName("Meta"); 
     modelBuilder.ComplexType<FeedMetaData>().Ignore(p => p.Data); 

     base.OnModelCreating(modelBuilder); 
    } 
} 
+2

這是一件非常光鮮的工作,也是我在其他地方沒有找到的技術,也是我自己不會輕易做出的。感謝你的分享! – 2014-10-16 01:37:23

+0

不要忘記,EF(至少EF6)將「_Serialized」或任何你稱爲你的財產的東西附加到你保存的字段中。在DB優先的情況下,這個信息可能是有用的 – 2015-03-29 16:53:03

+5

或者你可以在Data屬性中放置'[NotMapped]'。 – affan 2015-06-08 06:43:03

1

讓您的實體框架對象變得簡單並且具有數據庫中列的字符串屬性。

class Feed() 
{ 
    Guid FeedId { get; set; } 
    String Meta { get; set; } 
} 

創建保存方法和加載屬性爲這樣的:(它是因爲我已經使用EF一段時間,所以我不知道,如果你可以創建一個瞬態性能與這些getter/setter方法,或者你需要別的東西)

//Reading from string column Meta 
(ObjectMetaDictionary) XamlServices.Load(new StringReader(someFeed.Meta)); 

//Saving to string column Meta 
someFeed.Meta = XamlServices.Save(value); 

這會給你的項目帶來另一個問題。更改您的ObjectMetaDictionary可能會導致它無法正確反序列化數據庫。您的ObjectMetaDictionary成爲您的數據庫模式的一部分,您將需要相應地處理版本控制或更改。

+0

是的,這基本上是我現在的樣子,但是這個設計很弱,因爲這意味着我總是必須有一個超類來處理序列化/反序列化。我期望能夠使用Feed.Meta作爲ObjectMetaDictionary。 – kingdango 2013-02-08 19:42:18

+0

你在做什麼樣的EF映射,首先編碼,edmx,...? – 2013-02-08 19:57:19

+1

代碼首先,我更新了這個問題,以表明如果有人錯過了我設置的標籤。 – kingdango 2013-02-09 03:05:07