【问题标题】: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)实际上是在开始新事务之前尝试初始化数据库,所以不能使用。

已知的解决方法

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

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

    Sql("设置事务隔离级别读已提交");

这可行,但不方便且容易出错,因为开发人员通常不使用复制数据库。..

【问题讨论】:

    标签: c# sql-server entity-framework entity-framework-6 entity-framework-migrations


    【解决方案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”更改为您的隔离级别。

    【讨论】:

      猜你喜欢
      • 2013-12-29
      • 1970-01-01
      • 2017-10-31
      • 2013-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多