EF 4.1 Code First:多对多

use*_*552 1 c# entity-framework ef-code-first

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

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

表B的列:
-Id(PK) - >由数据库
-Description 生成的类型int

表C的列(对于此表,我不确定是否更好地添加由数据库生成的额外列Id作为前面的表): -
IdA(PK和实体A的外键)
-IdB(PK和外键实体B)

表B具有在种子方法上插入的固定值(覆盖).其条目如下所示:
Id描述
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();
Run Code Online (Sandbox Code Playgroud)

然后在保存对数据库的更改之后,我有数据库生成的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();
Run Code Online (Sandbox Code Playgroud)

我的问题是:
1)我不知道a.Id以前在context.A.Add(a)之后做context.SaveChanges因为它是由数据库生成的.
2)如果在context.C.Add(c)之后context.SaveChanges失败了,我怎么能回滚以前完成的工作?:
context.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
Run Code Online (Sandbox Code Playgroud)

怎么解决这个?

Sla*_*uma 5

这不是您使用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; }
}
Run Code Online (Sandbox Code Playgroud)

从集合中,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();
Run Code Online (Sandbox Code Playgroud)

这将创建一个新的A和插入之间的关系行ab进入链接表.