为了使用数据库优先方法创建多对多关系,您需要设置遵循特定规则的数据库架构:
- 创建一个
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 { ... } }
这些导航集合是同一个多对多关系的两个端点。 (如果您想通过多对多关系链接两个不同的表,例如表A 和B,一个导航集合(Bs)将在实体A 中,另一个(@ 987654344@) 将在实体 B 中。但是因为您的关系是“自引用”的,所以两个导航属性都在实体 Product 中。)
这两个属性的含义是:Products是与给定产品相关的产品,Products1是与给定产品相关的产品。例如:如果关系意味着一个产品需要其他产品作为部件来制造,并且您有产品“笔记本电脑”、“处理器”、“硅芯片”,那么“处理器”是由制成的“硅芯片”(“硅芯片”是Processor 产品实体的Products 集合中的一个元素)并且由“笔记本”使用(“笔记本”是Products1 Processor 产品实体的集合)。代替 Products 和 Products1 名称 MadeOf 和 UsedBy 会更合适。
如果您只对关系的一侧感兴趣,则可以安全地从生成的模型中删除其中一个集合。只需在模型设计器界面中删除例如 Products1。您还可以重命名属性。关系仍然是多对多的。
编辑
正如评论中所问的那样,使用代码优先方法的模型和映射将是:
型号:
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");
});
}
}