2012-07-02 18 views
8

Tengo Code First class/table y uno de los campos tiene type string/nvarchar. Esta cadena es una representación JSON de la instancia de MyClass. Me gustaría operar en código solo con instancias de MyClass, pero almacenarlo como una cadena (JSON) en la base de datos. Digamos que mi mesa se ve así:Entity Framework: Serialize/Deserialize JSON column behind the scene

public class Message 
{ 
    [Key] 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public string JsonDefinition { get; set; } 
} 

yo preferiría tenerlo como esto

public class Message 
{ 
    [Key] 
    public int Id { get; set; } 
    public string Title { get; set; } 
    [JSON] 
    public MyClass JsonDefinition { get; set; } 
} 

Dónde JSON es un atributo personalizado que le dice a EF para almacenar el campo como cadena serializada de ejemplo MiClase . Y al mismo tiempo, dice EF: "una vez que extrae la entidad, reemplace la cadena JsonDefinition con una instancia deserializada de MyClass"

¿Es posible lograrlo con los mecanismos EF 4 existentes? Si es así, ¿cómo?

Gracias de antemano.

EDIT: MyClass podría ser un diccionario o cualquier otro tipo complejo.

+0

tis puede ayudar: http://www.reddnet.net/entity-framework-json-column/ –

Respuesta

8

No directamente. Siempre debe tener su propiedad de cadena presente en su clase porque EF lo exige para su persistencia. También puede tener su propiedad MyClass no mapeada, pero debe manejar manualmente la serialización y la deserialización y sincronizar esas propiedades.

La solución ingenua es implementar INotifyPropertyChanged en su MyClass y garantizar que cada cambio en el valor MyClass o en cualquiera de sus propiedades desencadenará la serialización JSON a la propiedad de cadena. Esta solución ingenua funciona para algunos problemas simples, pero en este caso es realmente mala idea porque puede tener un gran impacto en el rendimiento si modifica muchas propiedades en la propiedad MyClass asignada.

Otra forma es utilizar los ganchos de EF para la materialización y guardar los cambios. Tendrá que manejar el evento ObjectContext.ObjectMaterialized (puede obtener ObjectContext desde DbContext a través de IObjectContextAdapter implementado explícitamente por DbContext). En este controlador de eventos usará el valor de la propiedad de cadena y deserializará su contenido a la propiedad MyClass. También deberá sobrescribir DbContext.SaveChanges donde buscará todas las instancias Message que se deben insertar o actualizar y usar su propiedad MyClass para obtener el valor actual y serializarlo en propiedad de cadena.

Lo que está buscando son algunos escenarios de mapeo complejos o conversiones mapeadas. EF no los admite, pero puede votar mi sugerencia en Data UserVoice.

+0

En lugar de utilizar los ganchos de Entity, ¿podría hacer que el getter de la propiedad haga la serialización bajo demanda, y el colocador realice la deserialización? y poblar el resto del objeto? –

+0

@KevinKibler Tiene los mismos problemas que la solución INotifyPropertyChanged, pero funcionaría. – Casey