事务控制
Fireasy 里的事务控制继承了 ADO.NET
的风格,不同的是,事务控制是由 IDatabase
来完成的,即使用 BeginTransaction 方法开启事务,查询执行成功时使用 CommitTransaction 方法提交事务,在异常中使用 RollbackTransaction 方法回滚事务。如下所示:
[TestMethod]
public void TestTransaction()
{
using (var db = DatabaseFactory.CreateDatabase())
{
try
{
db.BeginTransaction();
db.ExecuteNonQuery((SqlCommand)"DELETE products WHERE productid = 1");
db.CommitTransaction();
}
catch
{
db.RollbackTransaction();
throw;
}
}
}
BeginTransaction 方法可以指定事务的隔离级别,请参考 IsolationLevel
枚举。
1、事务嵌套
事务是可嵌套的,并且是安全的。在嵌套方法里再次调用 BeginTransaction 等方法时,如果 IDatabase
实例已经开启了事务,则会忽略。如下所示:
[TestMethod]
public void TestDeleteCustomers(string customerId)
{
using (var db = DatabaseFactory.CreateDatabase())
{
try
{
db.BeginTransaction();
TestDeleteOrders(customerId); //调用另一个方法
var parameters = new ParameterCollection();
parameters.Add("customer_id", customerId);
db.ExecuteNonQuery((SqlCommand)"DELETE customers WHERE customerid = @customer_id", parameters);
db.CommitTransaction();
}
catch
{
db.RollbackTransaction();
throw;
}
}
}
public void TestDeleteOrders(string customerId)
{
using (var db = DatabaseFactory.GetDatabaseFromScope() ?? DatabaseFactory.CreateDatabase())
{
try
{
db.BeginTransaction();
var parameters = new ParameterCollection();
parameters.Add("customer_id", customerId);
db.ExecuteNonQuery((SqlCommand)@"DELETE orders WHERE customerid = @customer_id", parameters);
db.CommitTransaction();
}
catch
{
db.RollbackTransaction();
throw;
}
}
}
如果调用 TestDeleteCustomers 方法,则嵌套方法 TestDeleteOrders 不会再次开启事务,提交和回滚事务都不会做任何处理。如果是直接调用 TestDeleteOrders 方法,则它会开启事务,提交和回滚事务都有效。
2、分布式事务
是支持分布式事务的,但需要外部环境的支持,比如开启 DTC
(Distributed Transaction Coordinator)服务,在方法中使用 TransactionScope
类即可,如下所示:
[TestMethod]
public void TestDistributedTransaction()
{
using (var scope = new TransactionScope())
using (var db = DatabaseFactory.CreateDatabase())
{
db.ExecuteNonQuery((SqlCommand)"DELETE products WHERE productid = 1");
scope.Complete();
}
}