I want to store an object that contains a List of primitives using EF.
public class MyObject {
public int Id {get;set;}
public virtual IList<int> Numbers {get;set;}
}
I know that EF cannot store this, but I’d like to know possible solutions to solve this problem.
The 2 Solutions I can think of are:
1.Create a Dummy object that has an Id and the Integervalue, e.g.
public class MyObject {
public int Id {get;set;}
public virtual IList<MyInt> Numbers {get;set;}
}
public class MyInt {
public int Id {get;set;}
public int Number {get;set;}
}
2.Store the list values as a blob, e.g.
public class MyObject {
public int Id {get;set;}
/// use NumbersValue to persist/load the list values
public string NumbersValue {get;set;}
[NotMapped]
public virtual IList<int> Numbers {
get {
return NumbersValue.split(',');
}
set {
NumbersValue = value.ToArray().Join(",");
}
}
}
The Problem with the 2. approach is, that I have to create a Custom IList implementation to keep track if someone modifies the returned collection.
Is there a better solution for this?
Although I do not like to answer my own question, but here is what solved my problem:
After I found this link about Complex Types I tried several implementations, and after some headache I ended up with this.
The List values get stored as a string on the table directly, so it’s not required to perform several joins in order to get the list entries. Implementors only have to implement the conversation for each list entry to a persistable string (see the Code example).
Most of the code is handled in the Baseclass (PersistableScalarCollection). You only have to derive from it per datatype (int, string, etc) and implement the method to serialize/deserialize the value.
It’s important to note, that you cannot use the the generic baseclass directly (when you remove the abstract). It seems that EF cannot work with that. You also have to make sure to annotate the derived class with the
[ComplexType]attribute.Also note that it seems not to be possible to implement a ComplexType for
IList<T>because EF complains about the Indexer (therefore I went on with ICollection).It’s also important to note, that since everything is stored within one column, you cannot search for values in the Collection (at least on the database). In this case you may skip this implementation or denormalize the data for searching.
Example for a Collection of integers:
Usage example:
This is the baseclass that handles the persistence aspect by storing the list entries within a string: