我想执行一个SELECT查询,后跟一系列UPDATE查询(全部在同一个表上); UPDATE在一个单独的方法中实现,该方法被重复调用。如果其中一个UPDATE查询失败,我希望它们全部失败/回滚 - 所以我想在事务中登记它们。但是,我不确定应该在哪里打开SqlConnection
以避免任何问题。我目前的实现如下:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// execute a single SELECT here
using (TransactionScope scope = new TransactionScope())
{
for (int i=0; i<...; i++)
{
Update(); // UPDATE query
}
scope.Complete();
}
}
Update()
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// execute a single UPDATE here
}
}
这是否应该在所有情况下都按预期工作?
在SELECT之前打开连接是否可以,然后在Update()
方法中打开一个新连接?由于连接池,SELECT和UPDATE查询都使用相同的连接(connectionString
是相同的),但只有UPDATE查询才会在事务中登记,对吧?但是如果在Update()
中使用了不同的连接会发生什么?是否所有UPDATE查询仍按预期在事务中登记并以原子方式执行?
如果我理解正确,在关闭第一个连接后(执行SELECT的using
块之后)创建事务范围仍然有效,但会降低性能,因为连接将被关闭并需要重新连接打开了,对吗?或者实际上是为事务范围创建的新连接,并且每次调用Update()
时都会打开和关闭它?
答案 0 :(得分:8)
不,不会;它只能在你首先将释放连接回池中时才这样做 - 目前你同时有两个连接,所以它不可能是同一个东西。你需要重组一下:由于连接池,SELECT和UPDATE查询将使用相同的连接
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// execute a single SELECT here
} // <==== end the first connection
using (TransactionScope scope = new TransactionScope())
{
for (int i=0; i<...; i++)
{
Update(); // UPDATE query
}
scope.Complete();
}
在关闭第一个连接(...)后创建一个事务范围但会降低性能,因为连接将被关闭并需要重新打开,正确
没有;当你“关闭”它时,你实际上只是将它释放回游泳池;它不会关闭底层连接(除非您禁用了池)。关闭(或至少处置)是正常的和预期的。
但只有UPDATE查询才会在交易中登记,对吧?
更正,因为那只是在事务范围内打开连接的地方
但是如果在Update()中使用了不同的连接会发生什么?是否所有UPDATE查询仍按预期在事务中登记并以原子方式执行?
任何支持登记的连接(假设未在连接字符串中禁用)都将被登记。但是,根据服务器,这可能使用LTM或可能使用DTC。如果您想确定关于您的联系:控制它们:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// execute a single SELECT here
} // <==== end the first connection
using (TransactionScope scope = new TransactionScope())
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
for (int i=0; i<...; i++)
{
Update(connection); // UPDATE query
}
scope.Complete();
}
注意我在上面将connection
传递给Update
;这里显而易见将使用单个连接(假设Update
工作正常)。