0

我会向您展示有关“真实交易”和“伪交易”的一些信息。我认为实体框架实现了一个伪事务,我会告诉你为什么。

// 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();

请注意,EF 仅在调用 SaveChanges 并且仅当发票和客户端对象之间存在关系时才会更新 ID 值,否则将无法正常工作。

所以,我的问题是:在 unitOwWork 模式上使用“真实交易”是一种好习惯吗?为什么 EF 让我们有可能偶然发现像我向您展示的那样的坏问题?

4

1 回答 1

0

SaveChanges可以向数据库发送多个命令,在您的情况下,它将发送两条INSERT语句 - 未批处理和一个接一个。SaveChanges将语句包装到由实体框架管理的事务中,您无法控制其生命周期。它从开头开始,SaveChanges并在所有语句都已发送且在SaveChanges返回之前被提交或回滚。这笔交易是“真实的”。要么两个INSERTs 都会成功,要么都不成功。

在许多情况下,这已经足够且方便,您不必关心事务管理。

在您的特殊情况下,这还不够,创建和管理您自己的外部事务是正确的解决方案。如果Customer有导航属性到Invoice. 但是你不需要,所以你需要这个单独的事务来获取数据库生成的键值,并且仍然在一个事务中执行整个操作。

于 2013-05-21T20:49:37.487 回答