在MSSQL 2008上使用EF进行更新查询时,存在性能和锁问题.所以我把ReadUncommitted事务隔离级别,希望解决它,像这样,
先于
using (MyEntities db = new MyEntities())
{
// large dataset
var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact;
for (var item in data)
item.Flag = 0;
// Probably db lock
db.SaveChanges();
}后
using (var scope =
new TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions() { IsolationLevel = IsolationLevel.ReadUncommitted }))
{
using (MyEntities db = new MyEntities())
{
// large dataset but with NOLOCK
var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact;
for (var item in data)
item.Flag = 0;
// Try avoid db lock
db.SaveChanges();
}
}我们使用SQL profiler来跟踪。但是,对这些脚本进行了排序(对于第一个脚本,期望读取未提交的)。
审计登录
set transaction isolation level read committedSP:StmtStarting
SELECT
[Extent1].[ContactId] AS [ContactId],
[Extent1].[MemberId] AS [MemberId],
FROM [dbo].[Contact] AS [Extent1]
WHERE [Extent1].[MemberId] = @p__linq__0审计登录
set transaction isolation level read uncommitted虽然我可以重新发送这个请求并使其正确的顺序(将显示以下请求的read-uncommitted,相同的SPID),但我想知道为什么它在读取提交命令之后发送读未提交的命令,以及如何使用EF和修复?谢谢。
发布于 2017-01-21 04:47:33
我认为这是一个由审计登录事件引起的青鱼。这是,而不是,它显示了客户机告诉服务器'set事务隔离级别读取未提交‘的时刻。当从池中选择并重用该连接时,它将向您展示稍后的隔离级别。
我通过将Pooling=false添加到连接字符串来验证这一点。然后,审计登录总是显示事务隔离级别已提交。
到目前为止,我还没有在SQL中看到EF设置事务级别的时刻,也没有发现任何显式的begin tran。
我可以通过读取和记录级别来确认它是在某个地方设置的:
const string selectIsolationLevel = @"SELECT CASE transaction_isolation_level WHEN 0 THEN 'Unspecified' WHEN 1 THEN 'ReadUncommitted' WHEN 2 THEN 'ReadCommitted' WHEN 3 THEN 'Repeatable' WHEN 4 THEN 'Serializable' WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL FROM sys.dm_exec_sessions where session_id = @@SPID";
static void ReadUncommitted()
{
using (var scope =
new TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions{ IsolationLevel = IsolationLevel.ReadUncommitted }))
using (myEntities db = new myEntities())
{
Console.WriteLine("Read is about to be performed with isolation level {0}",
db.Database.SqlQuery(typeof(string), selectIsolationLevel).Cast<string>().First()
);
var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact; // large results but with nolock
foreach (var item in data)
item.Flag = 0;
//Using Nuget package https://www.nuget.org/packages/Serilog.Sinks.Literate
//logger = new Serilog.LoggerConfiguration().WriteTo.LiterateConsole().CreateLogger();
//logger.Information("{@scope}", scope);
//logger.Information("{@scopeCurrentTransaction}", Transaction.Current);
//logger.Information("{@dbCurrentTransaction}", db.Database.CurrentTransaction);
//db.Database.ExecuteSqlCommand("-- about to save");
db.SaveChanges(); // Try avoid db lock
//db.Database.ExecuteSqlCommand("-- finished save");
//scope.Complete();
}
}(我说“有点”是因为每个陈述都在各自的会话中运行)
也许这是一条很长的路要说,是的,EF交易是正确的,即使你不能通过Profiler证明它。
https://stackoverflow.com/questions/41759486
复制相似问题