首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Server 2008中快照隔离级别中的ADO.Net事务在提交/回滚后不更改为默认隔离级别

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

Stack Overflow用户
提问于 2014-08-04 23:56:05
回答 1查看 3.5K关注 0票数 1

我在C#中有以下代码,使用ADO.NET来使用快照隔离级别更新Server 2008 R2数据库中的数据。这段代码工作得很好。但是,如果在此之后转到我的ASP.Net应用程序中的另一个页面,在该数据库表与同一服务器上的另一个数据库表之间运行查询,则会得到一个错误,该错误如下:

System.Data.SqlClient.SqlException:快照隔离事务访问数据库'Member_Security‘失败,因为此数据库中不允许快照隔离。使用ALTER允许快照隔离。

如果该查询在快照事务代码之后运行,则会引发上面粘贴的错误:

代码语言:javascript
复制
select 
   e.EmpId, e.EmpHours, m.SecurityLevel, m.IsPriveleged 
from 
   Emp e 
inner join 
   Member_Security.dbo.Members m

如果我没有在快照级别的下面的代码中运行事务,那么就没有问题。

为什么会发生这种情况,我该如何纠正呢?

我认为在这种情况下,快照隔离级别不会重置到运行此代码之前的状态。

运行完美的代码:

代码语言:javascript
复制
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:

根据下面的url:在ADO.Net代码中使用非默认隔离级别时,需要显式设置隔离级别中的这一段,在使用默认隔离级别之外的隔离级别时,似乎存在问题。

事务提交或回滚后,对于处于自动提交模式( Server默认值)的所有后续命令,事务的隔离级别将保持不变。这可能产生意想不到的结果,例如可重复读取的隔离级别、持久化和将其他用户锁定在行之外。若要将隔离级别重置为默认的(READ提交),请执行Transact-SQL SET事务隔离级别READ COMMITTED语句,或调用SqlConnection.BeginTransaction,然后立即调用SqlTransaction.Commit。有关Server隔离级别的详细信息,请参阅Server联机丛书中的“数据库引擎中的隔离级别”。

更新2:

避免这种情况的唯一方法是将隔离级别设置为完成上述事务后提交的读取,即在上述事务的最后块中调用方法'ResetTransactionIsolationLevel‘。如果这样做,那么在快照隔离级别之后执行跨数据库查询时没有发现任何问题。我添加了finally块,以在上面的代码片段中显示该解决方案。

代码语言:javascript
复制
 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();
        }
    }
EN

回答 1

Stack Overflow用户

发布于 2014-08-05 00:00:46

从这里开始:在事务中使用http://msdn.microsoft.com/en-us/library/tcbchxcb(v=vs.110).aspx快照之前,必须通过设置ALLOW_SNAPSHOT_ISOLATION ON数据库选项来启用它的快照隔离。

在您的数据库上运行以下命令:

代码语言:javascript
复制
ALTER DATABASE MyDatabase
SET ALLOW_SNAPSHOT_ISOLATION ON

UPDATE如果希望在后续事务中读取提交的快照而不隐式地指定它,也可以运行:

代码语言:javascript
复制
ALTER DATABASE MyDatabase
SET READ_COMMITTED_SNAPSHOT ON

请注意,这不是读取提交的,而且所有数据仍在运行中,因此您确实需要考虑数据库和应用程序的容量。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25129291

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档