Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I Embed an object in an EF entity (serialize on save, deserialize on access)?

Tags:

I have a class that I want to keep meta data for -- there a several interaction scenarios so meta allows me to keep different meta for different interaction types.

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

I would like EF to serialize this ObjectMetaDictionary and store it as a string/VarChar in the database. When I retrieve a record I want it to be deserialized as an ObjectMetaDictionary.

Does EF support this? How can I do it?

I am using Entity Framework Code First.

SOLVED: I provided an answer below that solved my problem. I will accept this answer as soon as SO allows me to.

like image 605
kingdango Avatar asked Feb 08 '13 19:02

kingdango


People also ask

What is the difference between serialize and deserialize C#?

Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called deserialization.

What does it mean to serialize and deserialize data?

Data serialization is the process of converting an object into a stream of bytes to more easily save or transmit it. The reverse process—constructing a data structure or object from a series of bytes—is deserialization.

Can you serialize any object?

To serialize an object means to convert its state to a byte stream so way that the byte stream can be reverted back into a copy of the object. A Java object is serializable if its class or any of its superclasses implements either the java. io. Serializable interface or its subinterface, java.


2 Answers

Apparently this is actually quite easy. I was able to get it working thanks to some help from this previous SO answer.

Fluent configuration in OnModelCreating allows us to tell EF what to use as the value property for serializing to the DB and back out again.

Here's my solution:

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);     } } 
like image 70
kingdango Avatar answered Nov 11 '22 21:11

kingdango


Have your Entity Framework object be simple and have a String property for the column in the database.

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

Create methods that save and load the property as such: (it's been a while since I've used EF, so i'm not sure if you can create a transient property with these getter/setters or if you need something else)

//Reading from string column Meta (ObjectMetaDictionary) XamlServices.Load(new StringReader(someFeed.Meta));  //Saving to string column Meta someFeed.Meta = XamlServices.Save(value); 

This brings another whole issue to your project though. Changing your ObjectMetaDictionary might cause it to not deserialize from the database correctly. Your ObjectMetaDictionary becomes essentially part of your database schema and you will need to handle versioning or changes accordingly.

like image 27
Daniel Moses Avatar answered Nov 11 '22 23:11

Daniel Moses