我正在使用带有DataTables的SqlDataAdapter.Update来更新单个事务中的两个SQL表。如果任一插入失败,我想回滚所有数据。这是我的代码:
using (var conn = new SqlConnection(_connectionString))
{
conn.Open();
using (var scope = new TransactionScope())
{
// Insert first table
using (var command = conn.CreateCommand())
{
command.CommandText =
@"INSERT INTO TableA(Id, Data)
VALUES(@id, @data)";
command.CommandType = CommandType.Text;
command.Parameters.Add(new SqlParameter("@id", SqlDbType.Int) { SourceColumn = "Id" });
command.Parameters.Add(new SqlParameter("@data", SqlDbType.Char) { SourceColumn = "Data" });
var adapter = new SqlDataAdapter();
adapter.InsertCommand = command;
adapter.Update(tableADataTable);
}
// Insert second table
using (var command = conn.CreateCommand())
{
command.CommandText =
@"INSERT INTO TableB(Id, Data)
VALUES(@id, @data)";
command.CommandType = CommandType.Text;
command.Parameters.Add(new SqlParameter("@id", SqlDbType.Int) { SourceColumn = "Id" });
command.Parameters.Add(new SqlParameter("@data", SqlDbType.Char) { SourceColumn = "Data" });
var adapter = new SqlDataAdapter();
adapter.InsertCommand = command;
adapter.Update(tableBDataTable);
}
scope.Complete();
}
}
我遇到的问题是,如果在第二个命令执行期间抛出异常,则仍会提交来自第一个命令的数据。我需要明确回滚吗?或者是TransactionScope在使用SqlDataAdapter.Update时应该如何表现?
需要注意的是,最初我在TransactionScope using语句中创建了SqlConnection,但我将其移出,因为我收到的错误是我的数据库服务器没有为分布式事务正确配置。事实上我的SqlConnection创建是否与TransactionScope相关?
答案 0 :(得分:2)
我认为您需要在事务范围内移动conn.Open()
调用,以便它将在事务中登记。另外,请确保您的连接字符串中没有enslist=false;
。
答案 1 :(得分:1)
尝试将SqlConnection置于TransactionScope中,然后它应自动登记到事务中。
我认为在您的代码中,您需要手动将连接登记到事务中...查看这些链接中的示例。
http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx
很抱歉刚抓到你的OP - 也许是因为连接没有配置为自动登记到现有的事务中(我认为是连接字符串的成员)。
如果你没有调用Complete(或SqlTransaction上的Commit),它将自动回滚。
当然,在您当前的代码示例中 - 您可以安全地使用SqlTransaction对象,因为您不涉及多个连接/数据库。
答案 2 :(得分:0)
尝试插入此代码
command.CommandText = @"SET autocommit = 0";
command.ExecuteNonQuery();
command.CommandText = @"SET sql_mode=TRADITIONAL";
command.ExecuteNonQuery();