EF 4.1 代码优先:多对多

Posted

技术标签:

【中文标题】EF 4.1 代码优先:多对多【英文标题】:EF 4.1 Code First: Many to Many 【发布时间】:2013-05-18 16:17:35 【问题描述】:

我有 2 个实体,比如说 A 和 B。它们之间的关系是多对多的,所以我有另一个实体,比如说 C。

表 A 的列: -Id (PK) -> 输入数据库生成的 int -PropertyA1 -PropertyA2 -PropertyA3

表 B 的列: -Id (PK) -> 输入数据库生成的 int -描述

表 C 的列(对于这个表,我不确定是否最好添加一个由数据库生成的额外列 ID 作为以前的表): -IdA(PK 以及实体 A 的外键) -IdB(PK 以及实体 B 的外键)

表 B 具有在种子方法中插入的固定值(被覆盖)。它的条目如下: 标识说明 1“一些描述1” 2“一些描述2” 3 “一些描述 3”

用户从一个表单中引入与表A相关的信息(propertyA1,...,propeprtyA3),然后点击一个按钮将数据保存到数据库中。

一旦用户点击按钮的表单将数据保存到数据库中,首先我会执行以下操作:

   A a = new A() PropertyA1=something_1,
                  PropertyA2=something_2,
                  PropertyA3=something_3 ;

   context.A.Add(a);
   context.SaveChanges();

那么在将更改保存到数据库之后,我有数据库生成的Id(在保存到数据库之前我没有id),即a.Id,现在我可以继续向表C添加一个条目:

  B b = this.ObtainAppropriateB();
  C c = new C() IdA = a.Id,
                 IdB = b.Id ;

  context.C.Add(c);
  context.SaveChanges();

我的问题是: 1) 我无法知道之前的 a.Id 以在 context.A.Add(a) 之后执行 context.SaveChanges,因为它是由数据库生成的。 2) 如果 context.C.Add(c) 之后 context.SaveChanges 失败,我该如何回滚之前的工作?: 上下文.A.Add(a); context.SaveChanges();

我无法执行以下操作,因为我之前没有 a.Id 来执行 SaveChanges:

   A a = new A() PropertyA1=something_1,
                  PropertyA2=something_2,
                  PropertyA3=something_3 ;

   context.A.Add(a);
   B b = this.ObtainAppropriateB();
   C c = new C() IdA = a.Id,
                  IdB = b.Id ;

   context.C.Add(c);

   context.SaveChanges(); <--- I call it once to persist changes to database

如何解决?

【问题讨论】:

你是说A和B的关系是many-to-many 是的,有什么问题? 【参考方案1】:

这不是您使用 Entity Framework 处理多对多关系的方式。

首先,您的模型中不应有 C 实体,而是实体 AB 上的集合属性:

public class A

    public int AId  get; set; 
    public int PropertyA1  get; set; 
    public string PropertyA2  get; set; 
    public DateTime PropertyA3  get; set; 

    public ICollection<B> Bs  get; set; 


public class B

    public int BId  get; set; 

    // ...

    public ICollection<A> As  get; set; 

从集合中,EF 能够确定关系是多对多的,并且需要一个链接表 (C)。您可以使用 Fluent API 定义映射细节。

其次,一旦你有了导航集合,你就不需要关心 Id。您只需构建具有必要关系的对象图并将其保存到数据库中:

A a = new A()  PropertyA1 = something_1,
                PropertyA2 = something_2,
                PropertyA3 = something_3 ;
a.Bs = new List<B>();

B b = this.ObtainAppropriateB(); // must use same context instance

a.Bs.Add(b);

context.A.Add(a);
context.SaveChanges();

它将创建一个新的A,并将ab之间的关系行插入到链接表中。

【讨论】:

谢谢,它有效。正如 Carlos Company 上面所说的,我在考虑数据库术语而不是模型术语。我还是 EF 代码的新手...谢谢大家!【参考方案2】:

我认为问题在于您考虑的是数据库术语而不是模型术语。您应该忘记表 C,因为该表将由数据库生成。您应该在 A 类中有一个 B 的集合,在 B 类中有一个 A 的集合。然后指定多对多关系。如果将 B 添加到 A,并保存上下文,则适当的数据将添加到表 C。

【讨论】:

你说得对,我在考虑数据库术语而不是模型术语。我还是 EF 代码的新手...谢谢大家!

以上是关于EF 4.1 代码优先:多对多的主要内容,如果未能解决你的问题,请参考以下文章

使用 EF4 CTP4 代码优先方法生成的多对多表中的命名约定

EF 4.1 复杂关系的实体映射

如何使用 MVC3 多对多关系和 EF4.1 模型优先检索数据?

使用 linq/Entity Framework 查询多对多关系。代码优先

如何在 .NET EF Core 中实现自引用多对多关系

EF 代码首先使用有效负载、复合键或代理键进行多对多