【问题标题】:Supporting transactions in a custom DatabaseManager支持自定义 DatabaseManager 中的事务
【发布时间】:2014-01-22 14:11:21
【问题描述】:

假设我们有以下自定义 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();
}

【问题讨论】:

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


    【解决方案1】:

    第二种方案确实更好。

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

    最后,您的代码将比自己处理事务更简洁。

    【讨论】:

    • 第二种方案终于不能在IBM的DB2 for AS400数据库上正常工作了……
    • 为什么不行?它与 IBM 的 DB2 for z/OS 一起使用,它(据我所知)使用相同的客户端软件。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2011-04-03
      • 1970-01-01
      • 2014-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多