>我有以下类和接口。
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; }
}
对于上述模型,它生成下表结构
书 -->书号 , 书名 , 作者
笔 -->笔 , 颜色
标记 -->标签ID , 名称 ,书本ID , 笔笔ID
当我插入以下数据时
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();
它不会插入第二本书的标签数据
我想实现的是我想实现一个三表标记系统这里显示坚持我的类结构
是的,它不会存储其中一本书的标签信息,因为您的标签实例只能与单本书相关联。这需要你在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
创建为计算属性。从这些例子中可以明显看出任何关系的组合。
编辑:
如果不想在标记中公开导航属性,则必须使用流畅的 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 API 参考,但它不符合数据(适用于 CTP5)。