sql-server - .Net 为 SqlClient 使用带有准备好的语句的事务
问题描述
我正在尝试为脚本实现事务,但遇到了一个奇怪的问题。
当我尝试在事务中运行准备好的 SQL 语句时,它失败了,因为它说在分配连接时它需要一个事务。
但是,这如何与准备好的语句一起使用,因为我打算让多个事务都使用相同的准备好的语句。
我的代码如下
class dbTest {
public static SqlConnection db;
public static SqlCommand query;
static void Main(string[] args) {
db = connect();
prepare();
transaction01();
transaction02();
transaction03();
}
public static void prepare() {
query = new SqlCommand("select id from table where id = 1 for update", db);
query.Prepare();
}
public static void transaction01() {
SqlTransaction trans = db.BeginTransaction("Trn01");
SqlDataReader result = query.ExecuteReader();
while(result.Read()) { Console.WriteLine(result["id"]); }
result.Close();
trans.Commit();
}
public static void transaction02() {
SqlTransaction trans = db.BeginTransaction("Trn02");
SqlDataReader result = query.ExecuteReader();
while(result.Read()) { Console.WriteLine(result["id"]); }
result.Close();
trans.Commit();
}
public static void transaction03() {
SqlTransaction trans = db.BeginTransaction("Trn03");
SqlDataReader result = query.ExecuteReader();
while(result.Read()) { Console.WriteLine(result["id"]); }
result.Close();
trans.Commit();
}
}
如何将交易分配给现有的准备好的语句?
更新
更改了上面的代码以更好地显示问题。SQL 只准备一次,但我会将它用于多个事务(或者至少我想要)
再次更新
我已将下面的答案标记为正确答案,因为它看起来是实现此目标的最佳方法,但在这个非常小的示例中,我需要使用query.Transaction
got it working
public static void transaction01() {
SqlTransaction trans = db.BeginTransaction("Trn01");
query.Transaction = trans; // this line fixed it
SqlDataReader result = query.ExecuteReader();
while(result.Read()) { Console.WriteLine(result["id"]); }
result.Close();
trans.Commit();
}
解决方案
使用 SqlTransaction 时,必须显式设置SqlCommand.Transaction,即使在 SQL Server 中登记当前事务不是可选的。
select ... for update
不是有效的 SQL Server 语法,而是使用 UPDLOCK 读取表并在事务期间保留限制性锁。例如select id from table with (updlock) where id = 1
当我尝试运行准备好的 SQL 语句时
- 在 SQL Server 中使用准备好的语句很少有用。即使没有它,查询计划缓存也会自动发生,当您使用不同的参数多次执行 SqlCommand 时,它实际上只是减少了网络上请求的大小。
但是准备好的 SqlCommand 仍然绑定到单个 SqlConnection,它的生命周期通常很短,从而最大限度地减少了准备 SqlCommand 的潜在好处。
推荐阅读
- python - 数组中字符串之间的常用字符
- android - 有没有一种简单的方法可以从 Kotlin 的字符串资源文件中获取具有默认值的数据类对象?
- sql - 当我们在语句中使用联接时,在选择语句中使用案例表达式时出错
- python - numpy.random.randint 比 random.randint 慢
- javascript - Javascript regex - 重用模式来捕获组
- email - 在 yii2 中用作邮件附件的 PDF 生成器的更好解决方案
- python - CNN 时如何检查图像大小?
- sql - 编写 SQL 查询以查找链接到相同用户 ID 的不同用户
- mysql - 不同的SQL写法造成不同的时间成本
- java - 使用 SimpleDateFormatter 获得不一致的结果