来自SQL Server 2008 R2中的快照隔离级别中的ADO.Net的事务在提交/回滚后不会更改为默认隔离级别

时间:2014-08-04 23:56:06

标签: c# asp.net sql-server-2008 ado.net snapshot

我在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();
        }
    }

1 个答案:

答案 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,因此您确实需要考虑数据库和应用程序的容量。