C# 实体框架6.0:如果一个实体需要为另一个实体分配Id,我如何确保两个实体之间的事务完整性?
关于在一个事务中多次调用dbContext.SaveChanges,我看到了许多问题和建议。 有人说这应该避免。这篇深入的文章真的值得一读 在我的特定场景中,实体B具有对实体A的Id引用 在一个创建场景中,我创建一个并调用savechanges以获得数据库分配的.Id。 然后我创建实体B,就像新的B(A.Id,…) 然后再次调用savechanges。在伪代码中可能是这样的C# 实体框架6.0:如果一个实体需要为另一个实体分配Id,我如何确保两个实体之间的事务完整性?,c#,entity-framework,transactionscope,C#,Entity Framework,Transactionscope,关于在一个事务中多次调用dbContext.SaveChanges,我看到了许多问题和建议。 有人说这应该避免。这篇深入的文章真的值得一读 在我的特定场景中,实体B具有对实体A的Id引用 在一个创建场景中,我创建一个并调用savechanges以获得数据库分配的.Id。 然后我创建实体B,就像新的B(A.Id,…) 然后再次调用savechanges。在伪代码中可能是这样的 using(var tx = dbContext.BeginTransaction()) { var a = n
using(var tx = dbContext.BeginTransaction())
{
var a = new A();
dbContext.Add(a); //a.Id is null
dbContext.saveChanges(); // a.Id has now been initialized
var b = new B(a.Id); //I want to create b in a valid state so a.Id cannot be null
dbContext.SaveChanges();
tx.Commit();
}
(我知道伪代码缺少异常处理逻辑…)
为什么这是一个问题?
是因为无法回滚savechanges吗
我知道我可以重新建模,但这是不可能的,因为我们与一些遗留系统共享数据库,所以数据库不能轻易更改,如果可能的话
什么是替代解决方案?请使用以下方法:
public class A
{
[Key]
public int Id { get; set; }
public int BId { get; set; }
[ForeignKey("BId")]
public B B { get; set; }
}
public class B
{
[Key]
public int Id { get; set; }
}
然后只需将新创建的B
分配给A
的导航属性:
using (var transaction = dbContext.BeginTransaction())
{
var a = new A();
a.B = new B();
dbContext.Add(a);
dbContext.saveChanges();
transaction.Commit();
}
使用这样的方法:
public class A
{
[Key]
public int Id { get; set; }
public int BId { get; set; }
[ForeignKey("BId")]
public B B { get; set; }
}
public class B
{
[Key]
public int Id { get; set; }
}
然后只需将新创建的B
分配给A
的导航属性:
using (var transaction = dbContext.BeginTransaction())
{
var a = new A();
a.B = new B();
dbContext.Add(a);
dbContext.saveChanges();
transaction.Commit();
}
考虑到实体框架确实支持显式事务,问题是什么?您似乎为一个功能编写了伪代码,而您的伪代码实际上调用了一个存在的方法,而您似乎错过了该功能。你费心看文件了吗?标题为“处理事务(EF6及以后)”。SaveChanges使用内部事务。更改分配已经是原子性的。真正的问题是什么?仅仅因为有人在某个地方写了你应该多次调用
SaveChanges
,并不意味着这是正确的。事实上,为什么你的代码要调用它两次??。如果你使用正确的关系,就没有理由分配ID。EF将识别新的/修改过的类,并生成SQL语句,这些语句将按注释的正确顺序插入新对象。是的,我读过关于交易的文章。在某些情况下,我可能更喜欢只按Id引用,而不使用对象关系。我的代码第一次调用SaveChanges是为了获得A的Id,以便初始化B。我有两个问题:1)我不清楚为什么调用savechages两次是不好的。2) 解决问题的其他方法。我很感激你给我的建议……考虑到实体框架确实支持显式事务,问题是什么?您似乎为一个功能编写了伪代码,而您的伪代码实际上调用了一个存在的方法,而您似乎错过了该功能。你费心看文件了吗?标题为“处理事务(EF6及以后)”。SaveChanges使用内部事务。更改分配已经是原子性的。真正的问题是什么?仅仅因为有人在某个地方写了你应该多次调用SaveChanges
,并不意味着这是正确的。事实上,为什么你的代码要调用它两次??。如果你使用正确的关系,就没有理由分配ID。EF将识别新的/修改过的类,并生成SQL语句,这些语句将按注释的正确顺序插入新对象。是的,我读过关于交易的文章。在某些情况下,我可能更喜欢只按Id引用,而不使用对象关系。我的代码第一次调用SaveChanges是为了获得A的Id,以便初始化B。我有两个问题:1)我不清楚为什么调用savechages两次是不好的。2) 解决问题的其他方法。我很感谢您提出的建议..SaveChanges已经使用了一个事务。除此之外,使用导航属性是正确的处理方法relations@PanagiotisKanavos:correct-只是想保持代码与OPs“伪代码”类似:)SaveChanges已使用事务。除此之外,使用导航属性是正确的处理方法relations@PanagiotisKanavos:正确-只是想保持代码与OPs“伪代码”相似: