Sql server 让查询在提交之前读取数据-Sql Server
我有一个名为ProjectActivity的表 主键:ProjectCode和ActivityId,以及ProjectCode上的索引 我们的网站在该表上生成查询(不涉及其他表),并始终使用相同的项目代码请求行 有时,我们在c#中启动一个作业,删除具有特定项目代码的每一行,并在事务中为该特定项目代码插入新行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()) {
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
的情况下进行查询时读取过时或已删除数据的风险,这与我建议您的相同,只是隔离级别不同而已