如何为Entity Framework CodeFirst迁移设置隔离级别

如果针对为SQL Server复制发布的表运行entity framework迁移(自动或显式),则会出现以下错误:

您只能在READ COMMITTED或REPEATABLE READ隔离级别中指定READPAST锁

之前( 此处 )存在一些问题,但它们完全无法解决根本原因: entity framework迁移在Serializable隔离级别运行 (如SQL Server分析器中清楚显示)。

对于结构更改事务,这是一个安全的选择,但它与发布的sql server表不兼容。 与dbContext.SaveChanges()事务中使用的默认READ COMMITED SNAPSHOT级别不同,我还没有找到一种方法来为代码中的迁移实际设置不同的隔离级别:

  • Database.Initialize()期间似乎忽略了TransactionScope (设置事务隔离级别的经典方法Database.Initialize()

  • 最近引入的Database.BeginTransaction(isolationLevel)实际上尝试在启动新事务之前初始化数据库,因此无法使用。

已知的解决方法

  1. 生成到SQL脚本的所有迁移。 这是有效的,但基于代码的迁移是一个我不想错过的强大工具。

  2. 使用显式迁移,并使用类似的方法启动每个Up()Down()方法

    Sql(“set transaction isolation level read committed”);

这很有效,但由于开发人员通常不使用复制数据库,因此不方便且容易出错。

是否有助于创建您的onw Migrator?

 internal sealed class Configuration : DbMigrationsConfiguration { public Configuration() { SetSqlGenerator("System.Data.SqlClient", new SqlMigrator()); } private class SqlMigrator : SqlServerMigrationSqlGenerator { public override IEnumerable Generate( IEnumerable migrationOperations, string providerManifestToken) { yield return new MigrationStatement { Sql = "set transaction isolation level read committed" }; foreach (var statement in base.Generate(migrationOperations, providerManifestToken)) yield return statement; } } } 

您可以在迁移代码中编写和执行SQL:

在SQL Server 2012使用动态SQL之前:

 public override void Up() { Sql("DECLARE @SQL NVARCHAR(4000) = 'ALTER DATABASE '+ DB_NAME() +' SET ALLOW_SNAPSHOT_ISOLATION ON' ; EXEC sp_executeSql @SQL;", true); } 

对于SQL Server 2012或更高版本:

 public override void Up() { Sql("ALTER DATABASE CURRENT SET ALLOW_SNAPSHOT_ISOLATION ON",true); } 

将“ALLOW_SNAPSHOT_ISOLATION”更改为隔离级别。