事务控制


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