Entity Framework - 12. Transactions
[ 2009-04-02 09:23:27 | 作者: yuhen ]
EF 默认会实现一个隐式事务,注意看 ObjectContext.SaveChanges()。
当我们没有显式提供事务时,SaveChanges() 通过 Connection.BeginTransaction() 启动事务。我们用一个例子测试一下。
输出:
在上面这个例子中,我们人为制造了一个并发异常,但你会发现 AddToUsers() 同样没有成功,显示是 SaveChanges() 中事务起了作用。当然这个隐式事务范围也仅限于 SaveChanges() 内部,也就是说如果我们在 AddToUser() 后立即调用 SaveChanges(),那么是可以成功创建 "userx" 的。
输出:
我们可以显式启动一个事务,这样即便多次调用 SaveChanges() 也在同一个事务范围内。
输出:
这回虽然还是多次调用 SaveChanges(),但依然无法添加 "userx",显然这种显示事务生效了。当然,我们还可以用 TransactionScope 启动分布式事务。
评论Feed: http://www.rainsts.net/feed.asp?q=comment&id=800
public class ObjectContext : IDisposable
{
public int SaveChanges(bool acceptChangesDuringSave)
{
...
using (DbTransaction transaction = null)
{
if (flag2)
{
transaction = connection.BeginTransaction();
}
objectStateEntriesCount = this._adapter.Update(this.ObjectStateManager);
if (transaction != null)
{
transaction.Commit();
}
}
...
}
}当我们没有显式提供事务时,SaveChanges() 通过 Connection.BeginTransaction() 启动事务。我们用一个例子测试一下。
using (var context = new TestEntities())
{
context.AddToUsers(new User { Name = "userx", Age = 27 });
var user = context.Users.First(u => u.Name == "user1");
user.Age += 1;
// Make OptimisticConcurrencyException
using (var context2 = new TestEntities())
{
var user2 = context2.Users.First(u => u.Name == "user1");
user2.Age += 3;
context2.SaveChanges();
}
try
{
context.SaveChanges();
}
catch (OptimisticConcurrencyException ex)
{
Console.WriteLine("OptimisticConcurrencyException");
}
Console.WriteLine(context.Users.Count(u => u.Name == "userx"));
}输出:
OptimisticConcurrencyException 0
在上面这个例子中,我们人为制造了一个并发异常,但你会发现 AddToUsers() 同样没有成功,显示是 SaveChanges() 中事务起了作用。当然这个隐式事务范围也仅限于 SaveChanges() 内部,也就是说如果我们在 AddToUser() 后立即调用 SaveChanges(),那么是可以成功创建 "userx" 的。
using (var context = new TestEntities())
{
context.AddToUsers(new User { Name = "userx", Age = 27 });
context.SaveChanges();
var user = context.Users.First(u => u.Name == "user1");
user.Age += 1;
// Make OptimisticConcurrencyException
using (var context2 = new TestEntities())
{
var user2 = context2.Users.First(u => u.Name == "user1");
user2.Age += 3;
context2.SaveChanges();
}
try
{
context.SaveChanges();
}
catch (OptimisticConcurrencyException ex)
{
Console.WriteLine("OptimisticConcurrencyException");
}
Console.WriteLine(context.Users.Count(u => u.Name == "userx"));
}输出:
OptimisticConcurrencyException 1
我们可以显式启动一个事务,这样即便多次调用 SaveChanges() 也在同一个事务范围内。
using (var context = new TestEntities())
{
context.Connection.Open();
var trans = context.Connection.BeginTransaction();
try
{
context.AddToUsers(new User { Name = "userx", Age = 27 });
context.SaveChanges();
var user = context.Users.First(u => u.Name == "user1");
user.Age += 1;
// Make OptimisticConcurrencyException
using (var context2 = new TestEntities())
{
var user2 = context2.Users.First(u => u.Name == "user1");
user2.Age += 3;
context2.SaveChanges();
}
context.SaveChanges();
trans.Commit();
}
catch
{
Console.WriteLine("Transaction Roolback!");
trans.Rollback();
}
Console.WriteLine(context.Users.Count(u => u.Name == "userx"));
}输出:
Transaction Roolback! 0
这回虽然还是多次调用 SaveChanges(),但依然无法添加 "userx",显然这种显示事务生效了。当然,我们还可以用 TransactionScope 启动分布式事务。
using (var trans = new TransactionScope())
{
try
{
using (var context = new TestEntities())
{
context.AddToUsers(new User { Name = "userx", Age = 27 });
context.SaveChanges();
}
using (var context2 = new TestEntities())
{
var user = context2.Users.First(u => u.Name == "user1");
user.Age += 1;
// Make OptimisticConcurrencyException
using (var context3 = new TestEntities())
{
var user2 = context3.Users.First(u => u.Name == "user1");
user2.Age += 3;
context3.SaveChanges();
}
context2.SaveChanges();
}
trans.Complete();
}
catch
{
Console.WriteLine("Exception!");
}
}
[最后修改由 yuhen, 于 2009-04-02 09:24:20]
评论Feed: http://www.rainsts.net/feed.asp?q=comment&id=800
这篇日志没有评论。






