我会向你揭露有关“真实交易”和“伪交易”的事情。 我认为Entity Framework实现了一个伪事务,我会告诉你原因。
// Partial Code
// *** Transaction scenario *** //
ObjectContext ctx = new ...
ctx.Connection.Open();
using(var t = ctx.Connection.BeginTransaction())
{
var invoice = new invoice{ price=10, Customer="myClient"};
ctx.CreateObjectSet<invoice>().AddObject(invoice);
ctx.SaveChanges();
// here I 've the ID invoice (I mean it like identity autoincrement) and I can execute some business logic basis on ID value
var client = new client { Name="Robert", Address="some address", IdInvoice=invoice.ID}
ctx.CreateObjectSet<client>().AddObject(client);
ctx.SaveChanges();
// Persistence
t.Commit(); // some error? t.Rollback
}
// *** PSEUDO Transaction scenario *** //
ObjectContext ctx = new ...
var invoice = new invoice{ price=10, Customer="myClient"};
ctx.CreateObjectSet<invoice>().AddObject(invoice);
// here I haven't invoice ID (I mean it like identity autoincrement) and I CANNOT EXECUTE ANY business logic basis on ID value
var client = new client { Name="Robert", Address="some address", IdInvoice=invoice.ID} // BAD: its value is zero
ctx.CreateObjectSet<client>().AddObject(client);
// Persistence
ctx.SaveChanges();
请注意,只有在调用SaveChanges之后,EF才会更新ID值,并且只有在发票和客户端对象之间存在关系时才会更新,否则任何内容都无法正常工作。
所以,我的问题是:在unitOwWork模式上使用“真实交易”是不是很好? 为什么EF让我们有可能偶然发现像我给你看过的那个糟糕的问题?
答案 0 :(得分:0)
SaveChanges
可以向数据库发送多个命令,在这种情况下,它会发送两个INSERT
语句 - 未分页,一个接一个。 SaveChanges
将语句包装到由Entity Framework管理的transcation中,您无法控制其生命周期。它从SaveChanges
的开头开始,并在发送所有语句并且在SaveChanges
返回之前被提交或回滚。这笔交易是“真实的”。两个INSERT
都可以成功,也可以不成功。
在许多情况下,您不必关心事务管理就足够方便了。
在您的特殊情况下,仅仅创建和管理您自己的外部事务是正确的解决方案。如果Customer
具有Invoice
的导航属性,则不需要这样做。但是你没有,所以你需要这个单独的事务来获取数据库生成的键值,并仍然在事务中执行整个操作。