为了使用Database-First 方法创建多对多关系,您需要设置遵循某些规则的数据库模式:
- 创建以
Products
列ProductID
为主键的表
- 创建一个
ProductRelations
包含一列ProductID
和一列的表,RelatedID
并将两列都标记为主键(复合键)
- 不要在表中添加任何其他
ProductRelations
列。两个关键列必须是表中唯一的列,才能让 EF 将此表识别为多对多关系的链接表
- 在两个表之间
创建两个外键关系:
- 第一个关系将
Products
表作为主键表,ProductID
主键作为主键,ProductRelations
表作为外键表,仅ProductID
作为外键
- 第二个关系也有
Products
作为主键的表ProductID
作为主键表和只有作为外键ProductRelations
的表作为外键表RelatedID
- 为两个关系中的第一个启用级联删除。(你不能对两者都这样做。SQL Server 不允许这样做,因为它会导致多个级联删除路径。)
如果您现在从这两个表生成实体数据模型,您将只得到一个实体,即一个Product
实体(或者Products
如果您禁用单数化)。链接表ProductRelations
不会作为实体公开。
该Product
实体将有两个导航属性:
public EntityCollection<Product> Products { get { ... } set { ... } }
public EntityCollection<Product> Products1 { get { ... } set { ... } }
这些导航集合是同一个多对多关系的两个端点。(如果您有两个不同的表,您想通过多对多关系链接,例如 tableA
和B
,一个导航集合 ( Bs
) 将在 entityA
中,另一个 ( As
) 将在 entity 中B
。但是因为您的关系是“self -reference”两个导航属性都在实体中Product
。)
这两个属性的含义是:Products
是与给定产品相关的产品,Products1
是指给定产品的产品。例如:如果关系意味着一个产品需要其他产品作为零件来制造,并且您有产品“笔记本电脑”、“处理器”、“硅芯片”,那么“处理器”由“硅芯片”(“Silicon芯片”是产品实体Products
集合中的一个元素)并由一个“笔记本”使用(“笔记本”是产品实体集合中的一个元素)。代替and的名字and会更合适。Processor
Products1
Processor
Products
Products1
MadeOf
UsedBy
如果您只对关系的一侧感兴趣,则可以安全地从生成的模型中删除其中一个集合。Products1
只需在模型设计器界面中删除例如。您还可以重命名属性。关系仍然是多对多的。
编辑
正如评论中所问的那样,使用Code-First 方法的模型和映射将是:
模型:
public class Product
{
public int ProductID { get; set; }
public ICollection<Product> RelatedProducts { get; set; }
}
映射:
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");
});
}
}