2013-02-08 9 views
17

Ho una classe che desidero conservare per i meta dati: esistono diversi scenari di interazione, quindi meta mi consente di mantenere meta diversi per diversi tipi di interazione.Posso incorporare un oggetto in un'entità EF (serializza su salva, deserializza su accesso)?

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

Vorrei EF per serializzare questo ObjectMetaDictionary e conservarla come una stringa/VarChar nel database. Quando recupero un record, voglio che sia deserializzato come ObjectMetaDictionary.

L'EF supporta questo? Come posso farlo?

Sto utilizzando il codice del framework Entity First.

RISOLTO: Ho fornito una risposta di seguito che ha risolto il mio problema. Accetterò questa risposta non appena SO mi consentirà di farlo.

+0

UPDATE: ho iniziato ad usare MongoDB poco dopo aver scritto questa domanda. Con Mongo questa domanda non è nemmeno rilevante perché è così facile da fare. Ho adorato EF quando uso SQL ma preferirei avere Mongo in qualsiasi giorno della settimana e, basandomi su 14 anni di esperienza, direi che mongo si comporta meglio per web/app ogni giorno. – kingdango

risposta

22

Apparentemente questo è in realtà abbastanza semplice. Sono riuscito a farlo funzionare grazie all'aiuto di questo precedente SO answer.

La configurazione fluida in OnModelCreating ci consente di indicare a EF cosa usare come proprietà del valore per la serializzazione nel DB e di nuovo indietro.

Ecco la mia soluzione:

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

Questo è un lavoro molto ingegnoso, e una tecnica che non ho trovato discusso altrove, e una che non avrei facilmente risolto da sola. Grazie per aver condiviso! –

+0

Non dimenticare che EF (almeno EF6) aggiunge "_Serialized" o qualsiasi cosa tu abbia chiamato la tua proprietà sul campo, il tuo salvataggio. Nel caso di un primo approccio DB, questa informazione potrebbe essere utile –

+5

Oppure puoi semplicemente mettere '[NotMapped]' nella proprietà Data. – affan

1

Avere il proprio oggetto Entity Framework essere semplice e avere una proprietà String per la colonna nel database.

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

Creare metodi che salvare e caricare la proprietà in quanto tale: (è stato un po 'che ho usato EF, quindi non sono sicuro se è possibile creare una proprietà temporaneo con questi getter/setter o se hai bisogno di qualcos'altro)

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

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

Questo porta comunque un altro problema al tuo progetto. Cambiando il tuo ObjectMetaDictionary potresti farlo deserializzare dal database correttamente. Il tuo ObjectMetaDictionary diventa essenzialmente parte dello schema del tuo database e dovrai gestire il controllo delle versioni o le modifiche di conseguenza.

+0

Sì, questo è essenzialmente come ho ora ma questo design è debole perché significa che devo sempre avere una superclasse per gestire la serializzazione/deserializzazione. Sto cercando di essere in grado di utilizzare Feed.Meta AS ObjectMetaDictionary. – kingdango

+0

Che tipo di mappatura EF stai facendo, prima il codice, edmx prima, ...? –

+1

Codice Innanzitutto, ho aggiornato la domanda per indicarlo nel caso in cui qualcuno dimenticasse i tag impostati. – kingdango

Problemi correlati