EntityFramework同一张表多对多关系
Posted
技术标签:
【中文标题】EntityFramework同一张表多对多关系【英文标题】:EntityFramework Same Table Many to Many Relationship 【发布时间】:2012-08-27 14:04:15 【问题描述】:我有一个名为 Products 的表,其中显然包含产品。 但是,我需要创建相关产品。所以我所做的是创建一个名为 product_related 的联结表,它有两个 PK。 Products 表中的 ProductID 和 Products 表中的 RelatedID。
我已经使用 EF 并在其他表上设置了所有内容。我应该如何正确添加它以便与产品建立关系:
product.Products.Add(product object here)
。当然这里product
代表我使用db.Products.FirstOr...
从数据库中获取的产品对象。
我应该如何正确地做到这一点?多对多到同一张表?
谢谢。
【问题讨论】:
如果这将是生产软件,请不要在单个表上使用 M2M,它可以并且确实可以工作,但是维护起来很痛苦,我现在正在工作,但是如果到我回家时你还没有得到答案,我会给你一个合适的解决方案来解决你的问题。 您是问如何使用实体框架添加到product_related表中? @Chazt3n 有什么替代方案? 【参考方案1】:为了使用数据库优先方法创建多对多关系,您需要设置遵循特定规则的数据库架构:
创建一个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");
);
【讨论】:
Code-First 怎么样?您如何指定关系(使用 Fluent API)? @drzaus:见我的编辑。我之前实际上有这个答案,但是当我注意到 DB-First 被问到时,我把它删除了。现在从已删除的答案中获取代码:) 正是我要找的@Slauma 如果你想让延迟加载工作,不要忘记将RelatedProducts
属性标记为virtual
--- 否则你可能会发现它似乎总是空的,除非你特别包含/加载这些在你需要的时候。
不应该是:.HasMany(p => p.RelatedProducts) 吗?【参考方案2】:
让我们举个例子:
相关表
Related_id PK
Related_name
Date
产品表
Product_id PK
Related_id FK
Product_Name
Date
如何在 EF 中表示
相关模型类命名为 RelatedModel
[Key]
public int Related_id get; set;
public string Related_name get;set
public Datetime Dateget;set;
产品模型类命名为 ProductModel
[Key]
public int Product_id get; set;
public string Product_name get;set
public string Related_id get;set
public Datetime Dateget;set;
[ForeignKey("Related_id ")] //We can also specify here Foreign key
public virtual RelatedModel Related get; set;
这样我们可以在两个表之间建立关系
现在在多对多关系的情况下,我想在这里再举一个例子
假设我有一个模型类Enrollment.cs
public class Enrollment
public int EnrollmentID get; set;
public int CourseID get; set;
public int StudentID get; set;
public decimal? Grade get; set;
public virtual Course Course get; set;
public virtual Student Student get; set;
这里CourseID和StudentId是两个外键
现在我有另一个类Course.cs,我们将在其中创建多对多关系。
public class Course
public int CourseID get; set;
public string Title get; set;
public int Credits get; set;
public virtual ICollection<Enrollment> Enrollments get; set;
希望这会有所帮助!!!
【讨论】:
你的回答离问题真的很远。 1)你的第一个例子是一对多的,2)第二个也是一对多的(尽管你说它是多对多的)。 3)您的关系不在同一张表之间,并且 4)他没有像您的示例那样使用 Code-First。以上是关于EntityFramework同一张表多对多关系的主要内容,如果未能解决你的问题,请参考以下文章