I have Code First class/table and one of the fields has type string/nvarchar. This string is JSON representation of MyClass instance. I'd like to operate in code with MyClass instances only, but store it as a string (JSON) in database. Let's say my table looks like this:
public class Message
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string JsonDefinition { get; set; }
}
I'd prefer to have it like this
public class Message
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
[JSON]
public MyClass JsonDefinition { get; set; }
}
Where JSON is a custom attribute which tells EF to store the field as serialized string of MyClass instance. And at the same time it says EF: "once you pull the entity, replace JsonDefinition string with deserialized instance of MyClass"
Is it possible to achieve with existing EF 4 mechanisms? If so, then how?
Thanks in advance.
EDIT: MyClass could be a Dictionary or any other complex type.
Not directly. You must always have your string property present in your class because EF demands it for persistence. You can also have your non mapped MyClass
property but you must manually handle serialization and deserialization and makes those properties in sync.
Naive solution is to implement INotifyPropertyChanged
in your MyClass and ensure that every change in MyClass
value or in any of its properties will trigger JSON serialization to the string property. This naive solution works for some simple problems but in this case it is really bad idea because it can have big performance impact if you modify a lot of properties on assigned MyClass
property.
Another way is using EF's hooks for materialization and saving changes. You will need to handle ObjectContext.ObjectMaterialized
event (you can get ObjectContext
from DbContext
via IObjectContextAdapter
explicitly implemented by DbContext
). In this event handler you will use string property's value and deserialize its content to MyClass
property. You will also have to override DbContext.SaveChanges
where you will look for all Message
instances which should be inserted or updated and use their MyClass
property to get current value and serialize it to string property.
What you are looking for are some complex mapping scenarios or mapped conversions. EF doesn't support them but you can vote for my suggestion on Data UserVoice.
I would try something as follows:
public class Message
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
[Column(TypeName = "jsonb")]
[JsonIgnore]
public string JMyClass { get; set; }
[NotMapped]
public MyClass JsonDefinition
{
get => JsonConvert.DeserializeObject<MyClass>(JMyClass );
set => JMyClass = JsonConvert.SerializeObject(value);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With