答案 0 :(得分:4)
您没有指定是否使用.NET 2.0,但我会做出这样的假设。 C#3.0示例代码如下:
using (var tx = new TransactionScope()) {
// Execute multiple DB statements inside here
ts.Complete();
}
如果任何DB语句失败,将永远不会到达ts.complete,并且该事务将在using语句结束时自动回滚。但是,这种方法的一个警告是,如果使用多个连接,最终会利用DTC,这意味着性能会降低。
已编辑以将SqlTransaction更改为TransactionScope
强制单个SQL连接以避免使用DTC的示例:
using (var tx = new TransactionScope())
using (var db = new SqlConnection(connString)) {
// Command 1
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
// Command 2
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
// Command 3
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
tx.Complete();
}
答案 1 :(得分:1)
在连接上创建事务,除了创建连接之外没有任何范围,因此您无法按照要求执行操作。重构,以便您可以在连接上顺序执行插入而不是同时执行或实现不同的机制来实现回滚(例如,如果稍后遇到错误,可以用作查找删除插入记录的插入键表。处理)
答案 2 :(得分:1)
您不使用一个连接和多个命令(实际上是在循环中重新创建一个命令)的原因是什么? 也许这个解决方案适合你:
public static void CommandExecNonQuery(SqlCommand cmd,
string query, SqlParameter[] prms)
{
cmd.CommandText = query;
cmd.Parameters.AddRange(prms);
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
}
static void Main(string[] args)
{
string insertQuery =
@"INSERT TESTTABLE (COLUMN1, COLUMN2) " +
"VALUES(@ParamCol1, @ParamCol2)";
using (SqlConnection connection =
new SqlConnection(connectionString))
{
using (SqlCommand command =
connection.CreateCommand())
{
SqlTransaction transaction = null;
try
{
// BeginTransaction() Requires Open Connection
connection.Open();
transaction = connection.BeginTransaction();
// Assign Transaction to Command
command.Transaction = transaction;
for (int i = 0; i < 100; i++)
CommandExecNonQuery(command, insertQuery,
new SqlParameter[] {
new SqlParameter("@ParamCol1", i),
new SqlParameter("@ParamCol2", i.ToString()) });
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
finally
{
connection.Close();
}
}
}
}
另见
Sql Server Transactions - ADO.NET 2.0 - Commit and Rollback - Using Statement - IDisposable
答案 3 :(得分:0)
我认为交易不能跨越多个连接。
在单独的连接中进行多次插入的原因是什么?我认为你通常会在一个连接中想要它们。