Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework 4 POCO with Dictionary

I have a POCO (Plain Old CLR Object)

public Foo
{
   public virtual int Id { get; set; }
   public virtual Dictionary<string, string> Stuff { get; set; }
   public virtual string More { get; set; }
}

Using the model first approach (i.e. I don't have a data model yet), how would I handle persisting Stuff (Dictionary)?

like image 203
Eric J. Avatar asked May 31 '10 21:05

Eric J.


2 Answers

This is not a true answer to the question, but since there are no other replies, I'll share what I did.

I simply created a new type {Id, Code, Text} and replaced my dictionary with a list of that type. I then do something like this to get the keys, values, or do a lookup:

List<string> texts = (from sv in q.SelectableValues select sv.Text).ToList();
List<string> codes = (from sv in q.SelectableValues select sv.Code).ToList();
string text = (from sv in q.SelectableValues where sv.Code == "MyKey" select sv.Text).First();

In my case the number of entries in the dictionary tends to be small. However, see this question for performance considerations when the dictionary/list is large.

like image 109
Eric J. Avatar answered Nov 09 '22 14:11

Eric J.


It appears the generalized, correct way to persist a Dictionary to a database would be the way it's Enumerated, since tables are essentially Sets with a loose concept of order - just like IEnumerable. That is, a Dictionary is enumerated as IEnumerator< KeyValuePair< TKey, TValue > >, and so the table should have 2 columns:

Key
Value

From there you have the existing EF conventions of Complex Types, where Key might actually be an object with many properties, and value as well. For example a dictionary of user objects might look like:

Username (TKey)
Address1 (TValue)
Address2 (TValue)

It's unfortunate this generalized pattern isn't built-in to EF; it ought to be proposed.

Instead of developing a specific type for your solution, you could use a generalized class that produces a Data Annotated version of KeyValuePair<>.

public class EFKeyValuePair<TKey, TValue>
{
    [Key]
    public TKey Key { get; set; }
    public TValue Value { get; set; }
}

I'm not certain how you'd ensure the table names would be written out in a logical and verifiable way however without inheriting this class and adding an attribute to each subclass. Perhaps the Fluent API could get you this final step (which I'm not very familiar with).

like image 33
Chris Moschini Avatar answered Nov 09 '22 14:11

Chris Moschini