Sql server 让查询在提交之前读取数据-Sql Server

Sql server 让查询在提交之前读取数据-Sql Server,sql-server,c#-4.0,isolation-level,Sql Server,C# 4.0,Isolation Level,我有一个名为ProjectActivity的表 主键:ProjectCode和ActivityId,以及ProjectCode上的索引 我们的网站在该表上生成查询(不涉及其他表),并始终使用相同的项目代码请求行 有时,我们在c#中启动一个作业,删除具有特定项目代码的每一行,并在事务中为该特定项目代码插入新行 using (var dbContextTransaction = db.Database.BeginTransaction()) {

我有一个名为ProjectActivity的表 主键:ProjectCode和ActivityId,以及ProjectCode上的索引 我们的网站在该表上生成查询(不涉及其他表),并始终使用相同的项目代码请求行

有时,我们在c#中启动一个作业,删除具有特定项目代码的每一行,并在事务中为该特定项目代码插入新行

            using (var dbContextTransaction = db.Database.BeginTransaction())
        {
            try
            {

                db.Database.ExecuteSqlCommand("delete FROM [TS_Repository].[dbo].[ProjectActivities] where ProjectCode = {0} ", project.Code);

                LogManager.WriteRequestLog("Deleted Existing Project Activities");

                if (ProjectActivities.Count > 0)
                {
                    db.Set<ProjectActivity>().AddRange(ProjectActivities);
                    db.SaveChanges();

                }

                dbContextTransaction.Commit();

                LogManager.WriteRequestLog("Refresh ProjectActivities succesfully for " + project.Title);
            }
            catch (Exception exc)
            {

                dbContextTransaction.Rollback();
                throw exc;
            }
        }
使用(var dbContextTransaction=db.Database.BeginTransaction())
{
尝试
{
db.Database.ExecuteSqlCommand(“从[TS_存储库].[dbo].[ProjectActivities]中删除,其中ProjectCode={0}”,project.Code);
LogManager.WriteRequestLog(“已删除的现有项目活动”);
如果(ProjectActivities.Count>0)
{
db.Set().AddRange(项目活动);
db.SaveChanges();
}
dbContextTransaction.Commit();
LogManager.WriteRequestLog(“为“+project.Title”成功刷新项目活动);
}
捕获(异常exc)
{
dbContextTransaction.Rollback();
抛出exc;
}
}
我们的问题是,在处理此事务(3/4分钟)时,我们的网站无法执行任何查询(整个表被锁定)。 我们应该获得这样一个场景: 在提交交易之前,网站应查询“旧”数据。这个场景可以实现吗?我可以理解,我们必须使用锁和隔离级别


提前感谢您提供的任何提示。

是的,您可以使用特定的隔离级别执行查询,该隔离级别可以在锁定表或行时读取数据。我不会参与关于读取未限制数据的风险的讨论,我想你已经知道了,@iamdave分享了一个关于这方面的好链接

当您想要读取未限制的数据时,有一些方法可以使用
EF
,但一种简单明了的方法是使用事务。在
TransactionScope
构造函数中,您可以设置
隔离级别,如下所示:

using (new TransactionScope(
           TransactionScopeOption.Required, 
           new TransactionOptions 
           { 
              IsolationLevel = IsolationLevel.ReadUncommitted 
           })) 
{
        // here you put your code
}

这里是另一本关于
EF
和隔离级别的好读物:

您告诉我的方向是正确的,但我想我需要快照隔离级别,因为我已经指定我需要阅读旧的行版本。也许我解释得不好

因此,我决定使用SNASPHOT:

using (var dbContextTransaction = db.Database.BeginTransaction(System.Data.IsolationLevel.Snapshot))
        {
            try
            {


                db.Database.ExecuteSqlCommand("delete FROM [TS_Repository].[dbo].[ProjectActivities] where ProjectCode = {0} ", project.Code);

                LogManager.WriteRequestLog("Deleted Existing Project Activities");

                if (ProjectActivities.Count > 0)
                {
                    db.Set<ProjectActivity>().AddRange(ProjectActivities);
                    db.SaveChanges();

                }

                dbContextTransaction.Commit();

                LogManager.WriteRequestLog("Refresh ProjectActivities succesfully for " + project.Title);
            }
            catch (Exception exc)
            {

                dbContextTransaction.Rollback();
                throw exc;
            }
        }
使用(var dbContextTransaction=db.Database.BeginTransaction(System.Data.IsolationLevel.Snapshot))
{
尝试
{
db.Database.ExecuteSqlCommand(“从[TS_存储库].[dbo].[ProjectActivities]中删除,其中ProjectCode={0}”,project.Code);
LogManager.WriteRequestLog(“已删除的现有项目活动”);
如果(ProjectActivities.Count>0)
{
db.Set().AddRange(项目活动);
db.SaveChanges();
}
dbContextTransaction.Commit();
LogManager.WriteRequestLog(“为“+project.Title”成功刷新项目活动);
}
捕获(异常exc)
{
dbContextTransaction.Rollback();
抛出exc;
}
}

也许您应该重新考虑清除然后重新填充项目代码集的决定-这听起来不是一个有效的方法。我不这么认为。我的活动经常更新。我应该检查每个id是否已经插入,如果已经插入,一些列是否已经更新,您谈论的风险涉及数据库一致性,或者它只考虑我读取可能被删除的数据这一事实?关于在隔离级别设置为
ReadUncommitted
的情况下进行查询时读取过时或已删除数据的风险,这与我建议您的相同,只是隔离级别不同而已