SQL Server 2017内存优化表更新时隔离级别异常求助
解决SQL Server内存优化表EF更新时的隔离级别异常问题
这个问题我之前踩过同款坑,核心原因是EF默认使用的Read Committed隔离级别,在内存优化表的非自动提交事务(EF的SaveChanges会开启隐式事务)中不被支持。哪怕你开启了数据库的快照隔离,EF也不会自动切换到对应级别,得咱们手动指定才行。下面给你几个可行的解决方案:
方案1:查询时直接添加表提示(最直接有效)
内存优化表允许通过WITH (SNAPSHOT)表提示强制指定隔离级别,咱们把查询语句改成带这个提示的形式,确保整个操作都符合要求:
using (var context = new MyDbEntities()) { var user = context.Users .FromSqlRaw("SELECT * FROM [User] WITH (SNAPSHOT) WHERE UserId = 1") .Single(); user.Name = "John"; context.SaveChanges(); }
这样查询阶段就用了Snapshot隔离级别,后续的更新操作也会继承这个上下文的隔离设置,直接避开触发异常的根源。
方案2:全局配置EF使用Snapshot隔离级别
如果不想每次写查询都加表提示,可以直接在DbContext里配置默认用Snapshot隔离:
方式A:DbContext全局配置
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer( "你的数据库连接字符串", opts => opts.UseSnapshotIsolation() // 开启默认Snapshot隔离 .EnableRetryOnFailure()); }
方式B:显式开启指定隔离级别的事务
如果你只想在特定操作中使用,也可以手动开启Snapshot事务:
using (var context = new MyDbEntities()) using (var transaction = context.Database.BeginTransaction(System.Data.IsolationLevel.Snapshot)) { var user = context.Users.Single(p => p.UserId == 1); user.Name = "John"; context.SaveChanges(); transaction.Commit(); }
这里要划重点:你之前执行的alter database MyDb set ALLOW_SNAPSHOT_ISOLATION ON是必要前提,但光开这个没用,必须让EF明确使用Snapshot隔离级别才能生效。
方案3:确认内存优化表的创建配置
最后可以快速检查下你的User表是否正确创建为内存优化表,确保DDL里包含关键配置:
CREATE TABLE [User] ( UserId INT PRIMARY KEY NONCLUSTERED, Name NVARCHAR(50) ) WITH (MEMORY_OPTIMIZED = ON);
从你的报错信息看这一步应该没问题,但确认下能避免一些隐性的配置疏漏。
内容的提问来源于stack exchange,提问作者Mehrdad
相关产品推荐
相关产品推荐

