2015-02-03 16 views
5

Sto cercando di trovare un modo per avere un oggetto che è una raccolta, ma quando viene salvato nel database diventa una stringa JSON. Come posso impostare l'Entity Framework 6.1 per fare questo? Esempio:Salva raccolta come JSON con Entity Framework

public class Company{ 

    public Company(){ 
     this.Times = new HashSet<DateTime>(); 
    } 

    public int Id {get;set;} 

    public string Name {get;set;} 

    public List<DateTime> Times {get;set;} 

} 

La società è un oggetto entità. Vorrei che Times fosse archiviato nel database come una stringa di volte. Mi piacerebbe serializzare durante la lettura dal database come un elenco di data e ora. Vorrei che la lista su save venisse riconvertita nella stringa json e salvata.

risposta

2

Il seguente dovrebbe funzionare (io ho usato Json.Net, ma si può cambiare a qualsiasi altra serializzatore):

public class Company 
{ 

    public int Id {get;set;} 

    public string Name {get;set;} 

    [NotMapped] 
    public List<DateTime> Times {get;set;} 

    [Column("Times")] 
    public string TimesSerialized 
    { 
     get 
     { 
      return JsonConvert.SerializeObject(Times); 
     } 
     set 
     { 
      Times = string.IsNullOrEmpty(value) 
        ? new List<DateTime>() 
        : JsonConvert.DeserializeObject<List<DateTime>>(value); 
     } 
    } 
} 

E 'possibile fare TimesSerialized privato, se si esegue il mapping manualmente.

+0

manualmente si intende attraverso l'api fluente? – rleffler

+1

@rleffler controlla questa risposta sulle proprietà private: http://stackoverflow.com/a/13810766/213725 – DixonD

5

Il problema con la risposta accettata è che eventuali modifiche ai contenuti della lista (aggiungendo, modificando o eliminando voci) non monitorati da EF.

Ecco la mia soluzione, ispirata allo this excellent blog post.

Questa classe si occupa di serializzazione e deserializzazione in modo che la raccolta può essere memorizzato in una sola colonna sul modello genitore:

[ComplexType] 
public class DateTimeCollection : Collection<DateTime> 
{ 
    public void AddRange(IEnumerable<DateTime> collection) 
    { 
     foreach (var item in collection) 
     { 
      Add(item); 
     } 
    } 

    [Column("Times")] 
    public string Serialized 
    { 
     get { return JsonConvert.SerializeObject(this); } 
     private set 
     { 
      if (string.IsNullOrEmpty(value)) 
      { 
       Clear(); 
       return; 
      } 

      var items = JsonConvert.DeserializeObject<DateTime[]>(value); 
      Clear(); 
      AddRange(items); 
     } 
    } 
} 

Questo è tutto! Ora puoi utilizzare questa nuova raccolta nella tua classe genitore esattamente come ti aspetteresti. Verranno tracciate le modifiche ai contenuti della collezione.

public class Company{ 
    // ... 
    public DateTimeCollection Times { get; set; } 
} 
+1

Risposta stupenda. Vale la pena includere il modo in cui è possibile definire ComplexType in 'DBCotext'. come: 'modelBuilder.ComplexType () .Property (p => p.Serialized) .HasColumnName (" Times ");' –

Problemi correlati