支持自定义DatabaseManager中的事务

时间:2014-01-22 14:11:22

标签: c# .net transactions ado.net .net-3.5

假设我们有以下自定义DbManager(它拥有的唯一私有成员是string connectionString):

public class SqlServerManager : DbManager
{
    public SqlServerManager(string connectionString)
        : base(connectionString) { }

    public override System.Data.DataTable GetDataTableFrom(string query, string tableName)
    {
        DataTable dt = new DataTable(tableName);

        if (string.IsNullOrEmpty(query))
            return dt;

        using (SqlConnection connection = new SqlConnection(this.ConnectionString))
        {
            SqlDataAdapter adapter = new SqlDataAdapter(query, connection);
            connection.Open();
            adapter.Fill(dt);
        }

        return dt;
    }


    public override object GetObjectFrom(string query)
    {
        return GetObjectFrom(query, 0);
    }

    public object GetObjectFrom(string query, int commandTimeout)
    {
        object result = null;
        if (!string.IsNullOrEmpty(query))
        {
            using (SqlConnection connection = new SqlConnection(this.ConnectionString))
            {
                SqlCommand command = new SqlCommand(query, connection);
                command.CommandTimeout = commandTimeout;
                command.Connection.Open();
                result = command.ExecuteScalar();
            }
        }
        return result;
    }

    public override void ExecuteNonQuery(string query)
    {
        ExecuteNonQuery(query, (SqlTransaction)null);
    }

    public void ExecuteNonQuery(string query, System.Data.SqlClient.SqlTransaction transaction)
    {
        if (!string.IsNullOrEmpty(query))
        {
            using (SqlConnection connection = new SqlConnection(this.ConnectionString))
            {
                SqlCommand command = new SqlCommand(query, connection, transaction);
                command.Connection.Open();
                command.ExecuteNonQuery();
            }
        }
    }
}

a)如何在这里添加一些交易支持?

说,使用共享事务(null或any)和几个Begin\Rollback\Commit\Transaction()

假设我们没有复杂的情况,我们班级只维持同一时间的一笔交易。

b)使用类似的东西可能更好(在示例中是类似的,但DB2Manager):

using (TransactionScope scope = new TransactionScope())
{
    // first connection Created/Disposed
    myDb2Manager.ExecuteNonQuery(mySql_1);
    // second connection Created/Disposed
    myDb2Manager.ExecuteNonQuery(mySql_2);
    // 3rd connection Created/Disposed
    myDb2Manager.ExecuteNonQuery(mySql_3);
    // commit everything
    scope.Complete();
}

2 个答案:

答案 0 :(得分:0)

第二种解决方案确实更好。

然后您的数据库管理员不需要了解有关该事务的任何信息。作为额外的优势,如果您只访问using块中的1个数据库管理器,则该事务将是本地事务,但如果您访问更多,则将自动提升为分布式事务。

最后,您的代码将比自己进行事务处理更清晰。

答案 1 :(得分:0)

您不需要将SqlTransaction的实例传递给ExecuteNonQuery方法。您正在执行ExecuteNonQuery(),它将执行查询(更新,删除或插入)作为针对DBMS的原子操作。所以交易的ACID属性是有保证的。但您仍然可以通过System.Transaction类“当前”静态属性访问正在运行的事务,以获取当前“或称为环境”事务。
你建议的第二种方法也没问题,但如果你正在使用一个数据库连接,也可以用你的方法替换,比如这个ExecuteNonQuery(mySql_1 + mySql_2 + mySql_3)。