事务处理
EF支持事务处理操作,以下语句会获取当前DbContext对象专用的DbContextTransaction事务处理的对象:
DbContextTransaction transaction = context.Database.BeginTransaction()
获取transaction之后,期间任何与context有关的数据均会被纳入此事务处理的范围。
调用transaction.Commit方法即可完成事务处理,若要放弃事务处理,调用transaction.Rollback方法即可,以下列举相关语句:
using(var transaction = context.Database.BeginTransaction)
{//事务处理操作
}
using语句是建立事务处理的常见语句,在结构上也比较容易理解,一旦using语句结束,transaction对象便自动调用Dispose回收事务处理对象。
下面通过一段示例代码来说明:
假设存在如下图实体类:
public class Product{public int Id { get; set; }public string Name { get; set; }public int Price { get; set; }public int SPrice { get; set; }}
编写一段事务代码如下图所示:
static void Main(string[] args)
{using (KTStoreModel context = new KTStoreModel()){using (var transaction = context.Database.BeginTransaction()){try{var products = context.Product;foreach (Product product in products){int p = (int)(product.Price * 0.5);product.SPrice = p;}int c = context.SaveChanges();transaction.Commit();Console.WriteLine("更新了{0}项数据",c);}catch(Exception ex){transaction.Rollback();Console.WriteLine("事务处理失败");}}}
}
共享事务处理连接
不同的context对象可以通过共享连接将数据的更新操作合并在相同的事务处理范围中,参考以下的设置:
KTStoreContext context_s = new kTStoreContext
(context.Database.Connection,contextOwnsConnection:false
)
为了共享事务处理,因此调用另一个版本的构造函数创建所需的context对象:除此之外,还要指定使用此连接的事务处理环境。
context_s.Database.UseTransaction(transaction.UnderlyingTransaction);
完成以上设置,context与context_s就会同时被限定在同一个事务处理范围中。
列举如下一个代码例子:
首先需要新增上下文类中的构造函数:
public class ConcurrencyCheckModel : DbContext
{public ConcurrencyCheckModel(): base("name=ConcurrencyCheckModel"){}public ConcurrencyCheckModel(DbConnection conn, bool contextOwnsConnection) : base(conn, contextOwnsConnection)//新增构造函数{}public virtual DbSet<Product> Product { get; set; }
}
static void Main(string[] args)
{using (ConcurrencyCheckModel context = new ConcurrencyCheckModel()){using (var transaction = context.Database.BeginTransaction()){try{var products = context.Product;foreach (Product product in products){int p = (int)(product.Price * 0.5);product.SPrice = p;}int c = context.SaveChanges();ConcurrencyCheckModel context_s = new ConcurrencyCheckModel(context.Database.Connection, contextOwnsConnection: false);context_s.Database.UseTransaction(transaction.UnderlyingTransaction);context_s.Database.ExecuteSqlCommand("Update product set SPrice = 0 Where Id = 10");transaction.Commit();Console.WriteLine("更新了{0}项数据",c);}catch (Exception ex){transaction.Rollback();Console.WriteLine("处理事务失败:{0}",ex.ToString());}}}
}