我有以下类和接口..
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; }
}
对于上述模型,它生成以下表结构
预订 - &gt; BookId,标题,作者
笔 - &gt; PenId,Color
标签 - &gt; TagId,Name,BookBookId,PenPenId
当我插入以下数据时
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();
它不会插入第二本书的标签数据
我想要实现的是我想实现一个三表标记系统 shown here坚持我的班级结构
答案 0 :(得分:1)
是的,它不会存储其中一本书的标签信息,因为您的标签实例只能与单本书相关联。这需要Book
和Tag
之间的多对多关系,但您的关系是一对多关系。 Pen
和Tag
之间的关系也是一对多关系。 Tag
表中的外键清晰可见。
问题是EF代码首先跳过ICollection<ITaggable> Items
- 代码首先不适用于接口。您必须将标记定义为:
public class Tag
{
[DatabaseGenerated(DatabaseGenerationOption.Identity)]
public Guid TagId { get; set; }
public string Name { get; set; }
public virtual ICollection<Book> Books { get; set; }
public virtual ICollection<Pen> Pens { get; set; }
}
这会在Book
和Tag
以及Pen
和Tag
之间的多对多之间映射多对多。如果您还希望收集ITaggable
,则可以展示连接Books
和Pens
的其他媒体资源。
如果您真的想要一对多的关系,那么您不能指望该标记会与多本书相关联,在这种情况下,您的Tag
实体应如下所示:
public class Tag
{
[DatabaseGenerated(DatabaseGenerationOption.Identity)]
public Guid TagId { get; set; }
public string Name { get; set; }
public virtual Book Book { get; set; }
public virtual Pen Pen { get; set; }
}
您可以再次创建Items
作为计算属性。从这些例子中可以明显看出任何关系的组合。
编辑:
如果您不想在Tag中公开导航属性,则必须使用fluent-api:
public class Context : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Pen> Pens { get; set; }
public DbSet<Tag> Tags { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Book>()
.HasMany(b => b.Tags)
.WithMany();
modelBuilder.Entity<Pen>()
.HasMany(p => p.Tags)
.WithMany();
}
}
可以在ADO.NET team blog找到更流畅的api参考,但这不符合数据(适用于CTP5)。