假设我们有以下自定义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();
}
答案 0 :(得分:0)
第二种解决方案确实更好。
然后您的数据库管理员不需要了解有关该事务的任何信息。作为额外的优势,如果您只访问using块中的1个数据库管理器,则该事务将是本地事务,但如果您访问更多,则将自动提升为分布式事务。
最后,您的代码将比自己进行事务处理更清晰。
答案 1 :(得分:0)
您不需要将SqlTransaction的实例传递给ExecuteNonQuery方法。您正在执行ExecuteNonQuery(),它将执行查询(更新,删除或插入)作为针对DBMS的原子操作。所以交易的ACID属性是有保证的。但您仍然可以通过System.Transaction类“当前”静态属性访问正在运行的事务,以获取当前“或称为环境”事务。
你建议的第二种方法也没问题,但如果你正在使用一个数据库连接,也可以用你的方法替换,比如这个ExecuteNonQuery(mySql_1 + mySql_2 + mySql_3)。