使用接口时实体框架代码首先生成奇怪的数据库模式
我有以下类和接口。
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; }
}
对于上述模型,它生成以下表结构
Book --> 书号、书名、作者
笔 --> PenId、颜色
标签 --> 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();
它不会插入第二本书的标签数据
我想要完成的是我想实现一个三表标记系统 此处显示 遵循我的类结构
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,它不会存储其中一本书的标签信息,因为您的标签实例只能与一本书相关联。这需要
Book
和Tag
之间存在多对多关系,但您的关系是一对多的。Pen
和Tag
之间的关系也是一对多的。通过Tag
表中的外键可以清楚地看到这一点。问题是
ICollectionEF 代码优先会跳过 Items
- 代码优先不适用于接口。您必须将标签定义为:这将映射
Book
和Tag
之间的多对多以及Pen
和Pen
之间的多对多代码>标签。如果您还想要ITaggable
的集合,您可以公开另一个连接Books
和Pens
的属性。如果您确实想要一对多关系,那么您不能期望该标签将与多本书关联,在这种情况下,您的
Tag
实体应如下所示:您可以再次创建
Items 作为计算属性。从这些例子中任何关系的组合都应该是显而易见的。
编辑:
如果您不想在标签中公开导航属性,则必须使用 Fluent-api:
可以在 ADO.NET 团队博客 但它不符合数据(适用于 CTP5)。
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
Book
andTag
but your relation is one-to-many. Relation betweenPen
andTag
is also one-to-many. That is clearly visible by foreign keys inTag
table.The problem is that
ICollection<ITaggable> Items
is 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
Book
andTag
and many-to-many betweenPen
andTag
. If you want also collection ofITaggable
you can expose another property concatenatingBooks
andPens
.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
Tag
entity should look like:Again you can create
Items
as 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).