我在C#中使用ADO.NET使用SNAPSHOT隔离级别更新SQL Server 2008 R2数据库中的数据。这段代码完美无缺。但是,如果我在我的ASP.Net应用程序中转到另一个页面,在此数据库表与同一服务器上的另一个数据库表连接之间运行查询,那么我收到一条错误消息:
System.Data.SqlClient.SqlException:快照隔离事务 无法访问数据库' Member_Security'因为快照隔离是 不允许在此数据库中。使用ALTER DATABASE允许快照 隔离。
如果它在SNAPSHOT事务代码之后运行,则抛出上面粘贴的错误的查询:
select
e.EmpId, e.EmpHours, m.SecurityLevel, m.IsPriveleged
from
Emp e
inner join
Member_Security.dbo.Members m
如果我没有在SNAPSHOT级别的下面的代码中运行事务,那么没有问题。
为什么会发生这种情况,我该如何纠正?
我认为在这种情况下,SNAPSHOT隔离级别不会重置为此代码运行之前的版本。
完美运行的代码:
con = new SqlConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["EMP"].ConnectionString;
con.Open();
tran = con.BeginTransaction(IsolationLevel.Snapshot);
cmd = new SqlCommand();
cmd.CommandTimeout = 0;
cmd.Connection = con;
cmd.Text = "Update emp set empcomm = 200 where empage > 40;"
cmd.Transaction = tran;
try {
cmd.ExecuteNonQuery();
tran.Commit();
}
catch(Exception ex)
{
try
{
if(tran != null)
tran.rollback();
}
catch{}
}
finally
{
DAL.ResetTransactionIsolationLevel();
} //NEED THIS TO SOLVE THIS PROBLEM
更新1:
使用ADO.Net代码中的默认级别以外的隔离级别似乎存在问题,根据本段从以下网址获取:Need to explicitly set Isolation Level when using non-default isolation level in ADO.Net code
提交或回滚事务后,对于处于自动提交模式(SQL Server默认值)的所有后续命令,事务的隔离级别仍然存在。这可能会产生意外结果,例如REPEATABLE READ持久化的隔离级别以及将其他用户锁定在一行之外。要将隔离级别重置为默认值(READ COMMITTED),请执行Transact-SQL SET TRANSACTION ISOLATION LEVEL READ COMMITTED语句,或者立即调用SqlConnection.BeginTransaction,然后立即调用SqlTransaction.Commit。有关SQL Server隔离级别的详细信息,请参阅数据库引擎中的"隔离级别"在SQL Server联机丛书中。
更新2:
我避免这种情况的唯一方法是在完成上述事务后将隔离级别设置为Read Committed,即调用方法' ResetTransactionIsolationLevel'在上述交易的最后一块中。如果我这样做,那么在SNAPSHOT隔离级别之后执行跨数据库查询时我没有看到任何问题。我添加了finally块以在上面的代码片段中显示此解决方案。
public static void ResetTransactionIsolationLevel()
{
SqlCommand cmd = new SqlCommand();
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["EMP"].ConnectionString);
try
{
cmd.CommandText = "set transaction isolation level read committed";
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
finally
{
cmd.Dispose();
conn.Close();
conn.Dispose();
}
}
答案 0 :(得分:2)
从这里开始:http://msdn.microsoft.com/en-us/library/tcbchxcb(v=vs.110).aspx 必须通过在事务中使用ALLOW_SNAPSHOT_ISOLATION ON数据库选项来启用快照隔离。
在您的数据库上运行:
ALTER DATABASE MyDatabase
SET ALLOW_SNAPSHOT_ISOLATION ON
更新如果您想在后续交易中读取已提交 SNAPSHOT 而不隐式指定,请同时运行:
ALTER DATABASE MyDatabase
SET READ_COMMITTED_SNAPSHOT ON
请注意,这不是读取提交的,并且所有数据仍然通过tempdb,因此您确实需要考虑数据库和应用程序的容量。