如何为实体框架代码优先迁移设置隔离级别
Posted
技术标签:
【中文标题】如何为实体框架代码优先迁移设置隔离级别【英文标题】:How to set the isolation level for Entity Framework CodeFirst Migrations 【发布时间】:2014-06-01 09:36:48 【问题描述】:如果您针对为 SQL Server 复制发布的表运行实体框架迁移(自动或显式),则会收到以下错误:
您只能在 READ COMMITTED 或 REPEATABLE READ 隔离级别
之前有关于此的问题 (here),但他们完全无法解决根本原因:Entity Framework 迁移在 Serializable
隔离级别运行(如在SQL Server 探查器)。
对于结构更改事务来说,这是一个安全的选择,但它与已发布的 sql server 表不兼容。与dbContext.SaveChanges()
事务中使用的默认 READ COMMITED SNAPSHOT 级别不同,我还没有找到一种方法来实际为代码中的迁移设置不同的隔离级别:
TransactionScope
(为事务设置隔离级别的经典方法)在Database.Initialize()
期间似乎被忽略了
最近引入的Database.BeginTransaction(isolationLevel)
实际上是在开始新事务之前尝试初始化数据库,所以不能使用。
已知的解决方法
生成到 SQL 脚本的所有迁移。这可行,但基于代码的迁移是我不想错过的强大工具。
使用显式迁移,并以类似的方式启动每个 Up()
和 Down()
方法
Sql("设置事务隔离级别读已提交");
这可行,但不方便且容易出错,因为开发人员通常不使用复制数据库。..
【问题讨论】:
【参考方案1】:创建 onw Migrator 会有所帮助吗?
internal sealed class Configuration : DbMigrationsConfiguration<SupplierEntities>
public Configuration()
SetSqlGenerator("System.Data.SqlClient", new SqlMigrator());
private class SqlMigrator : SqlServerMigrationSqlGenerator
public override IEnumerable<MigrationStatement> Generate(
IEnumerable<MigrationOperation> 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;
【讨论】:
+1。多么棒的答案,这确实有助于代码优先设计的复制数据库,其中问题没有得到很好的记录。我没有帽子,但如果我戴了,它会朝你的方向倾斜【参考方案2】:您可以在迁移代码中编写和执行 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”更改为您的隔离级别。
【讨论】:
以上是关于如何为实体框架代码优先迁移设置隔离级别的主要内容,如果未能解决你的问题,请参考以下文章