第一个疑问:-我们需要为Select sql语句创建TranscationScope吗?在我的ASP.NET MVC应用程序中,我尝试使用TranscationalScope将内容插入到一个表中。就在调用ExecuteNonQuery()之前,我在代码中放置了一个断点,并打开了一个SQL Server Management Studio,执行了一个select* from table;查询,但它没有等待并立即执行。理想情况下,TranscationScope通常会在表上设置一个锁,但我没有看到这一点。
此外,我编写了一个控制台应用程序(而不是使用SQL Server Management Studio),并使用TranscationScope执行相同的select查询,但它也无需等待即可立即执行,并且我的断点在我的ASP.NET web应用程序中仍处于活动状态。
下面是我在ASP.NET应用程序中编写的代码。
public void UpdateBranchDetails()
{
try
{
using (TransactionScope ts = new TransactionScope())
{
SqlCommand cmd = new SqlCommand(@"UPDATE BranchDetails
SET
[Reviews] = " + Reviews.ToString() + @"
,[Overall_Satisfaction] = " + Overall_Satisfaction.ToString() + @"
,[Goods_Condition_At_Delivery] = " + Goods_Condition_At_Delivery.ToString() + @"
,[Staff_Behaviour] = " + Staff_Behaviour.ToString() + @"
,[Timeliness] = " + Timeliness.ToString() + @"
,[Packaging_And_Loading_Professionalism] = " + Packaging_And_Loading_Professionalism.ToString() + @"
,[Likelihood_To_Recommned] = " + Likelihood_To_Recommned.ToString() + @"
WHERE BranchID = " + BranchID.ToString(), sqlConn);
sqlConn.Open();
cmd.ExecuteNonQuery();
ts.Complete();
}
}
catch (Exception ex)
{
}
finally
{
sqlConn.Close();
}
}在上面提到的代码sqlConn中,是SqlConneciton类的对象,并被声明为类成员。
发布于 2015-11-28 18:36:05
首先要考虑的是,使用无参数构造函数创建新的TransactionScope并不总是创建数据库事务。如果调用代码已经创建了一个TransactionScope,它将使用该事务(他们将其称为环境事务)。
第二件要考虑的事情是isolation level。这决定了数据库允许的并发类型。
默认isolation level为ISOLATIONLEVEL_SERIALIZABLE。这将锁定对已由并发事务读取的数据的任何写操作。
在您的示例中,您需要告诉数据库您所读取的数据需要哪种类型的并发。
-- I require all access to the data I query in this transaction to be serialized
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT * FROM [YourTable]然后执行您的代码。您会注意到,ExecuteNonQuery()调用将会停止,直到您对上面启动的事务执行COMMIT或ROLLBACK操作。
发布于 2015-11-29 20:01:34
我可以看到我的select sql查询正在等待事务完成。实际上,在我插入行内容的代码中,我没有执行ExecuteNonQuery()方法。我只是输入了transactionScope并设置了断点。我的假设是,只要输入TransactionScope,它就会锁定行以防止脏读。但这是错误的,理想情况下,我们必须向SQL server发出DML cmd,然后只有在我们提交事务之前,它才会锁定记录。
https://stackoverflow.com/questions/33969715
复制相似问题