C#/ SQL:在一个事务中执行多个插入/更新

时间:2011-01-28 15:06:10

标签: c# sql transactions insert

我有一个拥有10个房产的客户实体。

  • 其中7个属性保存在客户表中。
  • 其中3个属性保存在测试表中。

测试表中的3个属性是CustomerId,Label,Text。

当我查询这3个属性时,我得到3个这样的数据集:

CustomerId | Label  | Text
1005       | blubb  | What a day
1006       | hello  | Sun is shining
0007       |        |

当我保存它们时,我必须在测试表上调用我的存储过程3次

在我的SP中,我检查具有特定customerId AND Label的数据集是否已存在 然后我做一个更新,否则一个INSERT。

如何使用所有CommandText,CommandType,ExecuteNonQuery等东西调用存储过程3次?

4 个答案:

答案 0 :(得分:8)

最简单的方法:使用TransactionScope类。

只需将呼叫置于如下的块中即可:

using(TransactionScope ts = new TransactionScope()){

    using(SqlConnection conn = new SqlConnection(myconnstring)
    {
        conn.Open();
... do the call to sproc

        ts.Complete();
        conn.Close();
    }
}

[编辑]我还添加了SqlConnection,因为我非常喜欢这种模式。 using关键字确保关闭连接,如果发生错误则传输回滚

答案 1 :(得分:1)

嗯,跨越三个ExecuteNonQuery的SqlTransaction是最简单的,但有一些替代方案:

  • 使用XML数据类型以XML格式传递所有三个;将sproc中的XML(SQL服务器具有此功能)解析为3条记录
  • 使用“表值参数”在一次调用中传递它们 - 请注意,这需要在DB处进行额外定义以表示结构化数据
  • 如果数据量很大(3000而不是3),SqlBulkCopy进入临时表,然后运行一个sproc将数据移动到一个基于集合的操作中的真实表中

最后,注意“内部平台效应” - 它听起来有点像数据库中的数据库。

答案 2 :(得分:0)

有几个类继承自DbTransactionSqlTransaction的文档包含示例代码。

答案 3 :(得分:0)

您应该将INSERT封装到事务中。执行此操作的不好方法是在ADO.NET中使用TransactionScope,最好的方法是在proc中编写存储过程和BEGIN以及COMMIT / ROLLBACK事务。您不希望在维护事务时从客户端到服务器来回转换,因为您将损害concurreny和性能(在事务结束之前插入的资源会保留独占锁定。)

BEGIN TRAN 开始尝试     插入     插入     COMMIT TRAN 结束 开始捕捉     PRINT ERROR_MESSAGE() - 您可以在SQL Server 2012中使用THROW来重新删除错误     ROLLBACK END CATCH