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

C#/SQL:在一个事务中执行多个插入/更新,c#,sql,transactions,insert,C#,Sql,Transactions,Insert,我有一个拥有10处房产的客户实体 其中7个属性保存在customer表中 其中3个属性保存在测试表中 测试表中的3个属性是CustomerId、Label和Text 当我查询这3个属性时,我得到3个数据集,如下所示: CustomerId | Label | Text 1005 | blubb | What a day 1006 | hello | Sun is shining 0007 | | 当我保存它们时,我必须在测试表上调用我

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

  • 其中7个属性保存在customer表中
  • 其中3个属性保存在测试表中
测试表中的3个属性是CustomerId、Label和Text

当我查询这3个属性时,我得到3个数据集,如下所示:

CustomerId | Label  | Text
1005       | blubb  | What a day
1006       | hello  | Sun is shining
0007       |        |
当我保存它们时,我必须在测试表上调用我的存储过程3次

在我的SP中,我检查具有特定customerId和标签的数据集是否已经存在 然后我做一个更新或者一个插入


如何使用所有CommandText、CommandType、ExecuteOnQuery等内容调用存储过程3次?

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

好吧,跨越三个ExecuteOnQuery的SqlTransaction是最简单的,但也有一些替代方案:

  • 使用XML数据类型将所有三个作为XML传入;将存储过程中的XML(SQL server有相应的函数)解析为3条记录
  • 使用“表值参数”在单个调用中传递它们-请注意,这需要在数据库中添加表示结构化数据的定义
  • 如果数据量很大(3000而不是3),SqlBulkCopy将其复制到一个临时表中,然后运行存储过程,以在一个基于集合的操作中将数据移动到实际表中
最后,要注意“内部平台效应”——听起来有点像DB中的DB。

最简单的方法是:使用类

只需将调用放入如下块中:

using(TransactionScope ts = new TransactionScope()){

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

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

[Edit]我还添加了SqlConnection,因为我非常喜欢这种模式。using关键字确保连接已关闭,并且如果发生错误,事务将回滚。您应该将插入内容封装到事务中。不好的方法是在ADO.NET中使用TransactionScope,好的方法是编写一个存储过程并在进程内开始和提交/回滚事务。在维护事务时,您不希望在客户端和服务器之间来回切换,因为这样会损害concurreny和性能(在事务结束之前,插入的资源上会保留独占锁)

开始训练 开始尝试 插入 插入 提交传输 结束尝试 开始捕捉 打印错误消息()--您可以在SQL Server 2012中使用THROW来重新打印错误 回降
END CATCH

是否有一个对象代表客户,或您希望插入测试表中的实体?请给我一个跨越3 ExecuteOnQuery的sqltransaction的小片段?@Lisa我确信MSDN已经。。。既然您有using(){}功能,为什么还要在其中调用conn.Close()方法呢redundant@Redg:这是一个可读性的问题(因此,也是个人偏好)。SqlConnection的
Dispose()
方法确实会在需要时关闭它。但它不会关闭它两次。