I have following Classes and interfaces..
public interface ITaggable
{
ICollection<Tag> Tags { get; set; }
}
public class Book :ITaggable
{
[DatabaseGenerated(DatabaseGenerationOption.Identity)]
public Guid BookId { get;set; }
public string Title { get; set; }
public string Author { get; set; }
public virtual ICollection<Tag> Tags {get; set;}
}
public class Pen:ITaggable
{
[DatabaseGenerated(DatabaseGenerationOption.Identity)]
public Guid PenId { get; set; }
public string Color { get; set; }
public virtual ICollection<Tag> Tags {get; set;}
}
public class Tag
{
[DatabaseGenerated(DatabaseGenerationOption.Identity)]
public Guid TagId { get; set; }
public string Name { get; set; }
public virtual ICollection<ITaggable> Items { get; set; }
}
For the above model it generates the following table structure
Book –>
BookId , Title , Author
Pen –>
PenId , Color
Tag –>
TagId , Name ,BookBookId , PenPenId
And when i insert the following data
Tag tag = new Tag();
tag.Name = "Stationary";
Book b1 = new Book();
b1.Title = "Head first c#";
b1.Author = "Betty";
b1.Tags = new List<Tag>() { tag };
Book b2 = new Book();
b2.Title = "Head first Java";
b2.Author = "Katty";
b2.Tags = new List<Tag>() { tag };
Pen p = new Pen();
p.Color = "Red";
p.Tags = new List<Tag>() { tag };
context.Books.Add(b1);
context.Books.Add(b2);
context.Pens.Add(p);
context.SaveChanges();
It does not insert the Tag data for the second book
What i want to accomplish is that i want to implement a three table tagging system
shown here adhering to my class structure
Yes it will not store the tag info for one of the books because your tag instance can be associated only with single book. That would require your many-to-many relation between
BookandTagbut your relation is one-to-many. Relation betweenPenandTagis also one-to-many. That is clearly visible by foreign keys inTagtable.The problem is that
ICollection<ITaggable> Itemsis skipped by EF code first – code first doesn’t work with interfaces. You must define your Tag as:This will map many-to-many between
BookandTagand many-to-many betweenPenandTag. If you want also collection ofITaggableyou can expose another property concatenatingBooksandPens.If you really want one-to-many relation then you cannot expect that tag will be associated with multiple books and in such case your
Tagentity should look like:Again you can create
Itemsas computed property. Any combination of relation should be obvious from these examples.Edit:
If you don’t want to expose navigation properties in Tag you must use fluent-api:
Further fluent api reference can be found on ADO.NET team blog but it is not up to data (it is for CTP5).