为了创建多对多关系数据库优先方法您需要设置遵循某些规则的数据库架构:
- 创建一个
Products
有列的表ProductID
作为主键
- 创建一个
ProductRelations
有列的表ProductID
和一列RelatedID
并标记两列都作为主键(复合键)
-
不要向其中添加任何其他列
ProductRelations
table。两个键列必须是表中唯一的列,才能让 EF 将该表识别为多对多关系的链接表
- Create two foreign key relationships between the two tables:
- 第一个关系有
Products
表作为主键表ProductID
作为主键和ProductRelations
表作为外键表只有ProductID
作为外键
- 第二个关系也有
Products
表作为主键表ProductID
作为主键和ProductRelations
表作为外键表只有RelatedID
作为外键
- Enable 级联删除对于这两种关系中的第一种。 (您不能对两者都执行此操作。SQL Server 不允许这样做,因为这会导致多个级联删除路径。)
如果您现在从这两个表生成实体数据模型,您将得到只有一个实体,即Product
实体(或者也许Products
如果禁用单一化)。链接表ProductRelations
不会作为实体公开。
The Product
实体将有两个导航属性:
public EntityCollection<Product> Products { get { ... } set { ... } }
public EntityCollection<Product> Products1 { get { ... } set { ... } }
这些导航集合是同一多对多关系的两个端点。 (如果您有两个不同的表,您想通过多对多关系链接,例如表A
and B
, 一个导航集合 (Bs
) 将在实体中A
和另一个 (As
) 将在实体中B
。但是因为您的关系是“自引用”,所以两个导航属性都在实体中Product
.)
这两个属性的含义是:Products
是与给定产品相关的产品,Products1
是指给定产品的产品。例如:如果关系意味着某个产品需要其他产品作为零件来制造,并且您有产品“笔记本电脑”、“处理器”、“硅芯片”,那么“处理器”是made of“硅片”(“硅片”是一种元素Products
的集合Processor
产品实体)并且是used by一个“笔记本”(“笔记本”是Products1
的集合Processor
产品实体)。代替Products
and Products1
名字MadeOf
and UsedBy
那么会更合适。
如果您只对关系的一侧感兴趣,则可以安全地从生成的模型中删除其中一个集合。例如删除即可Products1
在模型设计器界面中。您还可以重命名属性。这种关系仍然是多对多的。
Edit
正如评论中所问,模型和映射代码优先方法将会:
Model:
public class Product
{
public int ProductID { get; set; }
public ICollection<Product> RelatedProducts { get; set; }
}
Mapping:
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.HasMany(p => RelatedProducts)
.WithMany()
.Map(m =>
{
m.MapLeftKey("ProductID");
m.MapRightKey("RelatedID");
m.ToTable("product_related");
});
}
}