TransactionScope 不使用 SqlDataAdapter.Update 回滚
我使用 SqlDataAdapter.Update 和 DataTables 在单个事务中更新两个 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();
}
}
我遇到的问题是,如果在第二个命令执行期间引发异常,则仍然会提交第一个命令中的数据。我需要明确回滚吗?或者使用 SqlDataAdapter.Update 时 TransactionScope 应该如何表现?
需要注意的是,最初我在 TransactionScope using 语句中创建了 SqlConnection,但我将其移出,因为我收到错误消息,表明我的数据库服务器尚未针对分布式事务进行正确配置。我的 SqlConnection 创建超出 TransactionScope 的事实是否相关?
I'm using SqlDataAdapter.Update with DataTables to update two SQL tables in a single transaction. If either insert fails I want to roll back all data. This is my code:
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();
}
}
The problem I'm having is that if an exception is thrown during the second command execution, data from the first command is still commited. Do I need to explicitly roll back? Or is how TransactionScope should behave when using SqlDataAdapter.Update?
Something to note is that originally I had the SqlConnection creation within the TransactionScope using statement, but I moved it out as I was receiving errors that my DB server hadn't been configured correctly for distributed transactions. Is the fact that my SqlConnection creation is outside TransactionScope related?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为您需要将 conn.Open() 调用移至事务范围内,以便它将自己纳入事务中。另外,请确保连接字符串中没有
enslist=false;
。I think you need to move your
conn.Open()
call inside the transaction scope so it will enlist itself in the transaction. Also, make sure you do not haveenslist=false;
in your connection string.尝试将 SqlConnection 放入 TransactionScope 中,然后它应该会自动加入事务。
我认为在您的代码中,您需要手动将连接登记到事务中...查看这些链接中的示例。
http:// /msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.enlistdistributedtransaction(v=VS.71).aspx
http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx
抱歉抓住了你的OP - 也许是因为连接没有配置为自动加入现有事务(我认为是连接字符串的成员)。
如果您不调用 Complete(或 SqlTransaction 上的 Commit),它将自动回滚。
当然,在当前的代码示例中 - 您可以安全地使用 SqlTransaction 对象,因为您不涉及多个连接/数据库。
Try placing your SqlConnection inside the TransactionScope, it should then automatically enlist in the transaction.
I think in your code, you need to manually enlist the connection into the transaction... review the examples in these links.
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.enlistdistributedtransaction(v=VS.71).aspx
http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx
Sorry just caught your OP - perhaps it's because the connection wasn't configured to automatically enlist into existing transactions (a member of the connection string I think).
If you don't call Complete (or Commit on a SqlTransaction) it will automatically rollback.
Of course, in your current code sample - you can safely use a SqlTransaction object as you aren't involving multiple connections/databases.
尝试插入这段代码
try inserting this code