Say you want to store an array of strings associated with an entity using EF? For example Tags on a Blog Post...

BlogEntry - ICollection<string>

public class BlogEntry {
    public int Id { get; set; }
    public string Title { get; set; }
    public string Text { get; set; }

    public ICollection<string> Tags { get; set; }
}

Hooked up to a DbContext

public class DataContext : DbContext {
    static DataContext() {
        DbDatabase.SetInitializer(
            new DropCreateDatabaseIfModelChanges<DataContext>());
    }

    public DbSet<BlogEntry> BlogEntries { get; set; }
}

With the appropriate .Config

<configuration>
  ...
  <connectionStrings>
    <add name="DataContext" connectionString="Server=.\sqlexpress;Database=Sandbox.EFArrayOfStrings;Integrated Security=true" providerName="System.Data.SqlClient" />
  </connectionStrings>
   ...
</configuration>

An gave it a whirl, the result was a database, a table, but no storage for the Tags collection.

Well, this isn't supported. What we have here is a One to Many relationship, and your Tags need their own table to store the data, for this to happen you need to define a Complex Type, which brings with it a number of restrictions.

BlogEntry - ICollection<Tag>

Firstly I define the complex type to contain my tags name

public class Tag {

    [Key]
    [Column(Order = 0)]
    public int BlogEntryId { get; set; }

    [Key]
    [Column(Order = 1)]
    public string Name { get; set; }
}

Rule no 1 of EF, every entity must have a Key, so that it can be distinguished, loaded and saved back to the same record.

If you were to have a one to one relationship you would only declare the Key as being the BlogEntry property, as we are One to Many, we need to make a compound key with the Name its-self - note this will restrict the collection to having a unique name, in this case this is what I want.

Finally with a compound key you need to tell EF what the column order will be so you see the ColumnAttribute added to both properties.

Now, I add the DbSet<Tag> to the DataContext, update my BlogEntryClass with ICollection<Tag> and run my test.

[TestMethod]
public void TestDataContext() {
    var dataContext = new DataContext();

    dataContext.BlogEntries.Add(
        new BlogEntry {
            Title = "Test",
            Text = "Some Test Content",
            Tags = new[] {
                       new Tag {Name = "Test"},
                       new Tag {Name = "EF Code-First"}
                   }
        });

    dataContext.SaveChanges();
}

A new table is created, with a compound key for BlogEntryId and Name and a foreign key link to the BlogEntry table

- that will do for me, here's a database diagram to illustrate the result further

Attached : VS 2010 Solution

comments powered by Disqus

On Twitter Follow MrAntix on Twitter

ptjmg3 46 minutes ago
ptjmg3

Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8 http://t.co/imFNsPyYRA 375 pic.twitter.com/Dbc5j6zzhh

ncover 53 minutes ago
ncover

RT @Azure: Learn how to use #Azure DocumentDB #Hadoop Connector with Azure #HDInsight! http://t.co/YGmy2loA1k http://t.co/ckedfnoS3pic.twitter.com/ckedfnoS32http://t.co/YGmy2loA1k

TheDaveKurth 53 minutes ago
TheDaveKurth

RT @msdev: The newest release of http://t.co/1eytkspG9I MVC addresses 13 issues. Here's the full list: http://t.co/Tm1D4JNzFR #webdehttp://t.co/Tm1D4JNzFRhttp://t.co/1eytkspG9I#webdev

JavaEmployer 58 minutes ago
JavaEmployer

#jQuery #prototype http://t.co/2fA7XXaTBV MVC expert with good UI(HTML, Jquery and CSS) Skills by askfarhan: hi... http://t.co/9vvKwf9eyp

DotNetCodeIT One hour ago
DotNetCodeIT

http://t.co/LCeVicE6vs MVC 5 with EF 6 - Working With Files http://t.co/wjNxL3h3Wl