• EF6:编写你自己的code first 数据迁移操作(睡前来一篇,翻译的)


    原英文版由EF团队成员 Rowan Miller 在2013年发表,此处只作翻译备忘。

    数据迁移提供了一套强类型API,用于执行通用的操作,比如CreateIndex("dbo.Blogs","Url")。同时,也提供了在一些特殊的情况下用户需要执行特殊SQL的接口,比如Sql("Grant Select On dbo.Blogs to guest);。当然,这个SQL的接口也有一些缺点——那就是一旦你写了SQL那么就意谓着你的程序不再数据库无关了(比如ORACLE的语法和SQL SERVER有时候并不一样,这造成了不兼容)。

    你可以把你需要的强类型API提交给ICECLOW。

    创建我们自己的操作

    我们打算添加一个允许我们将一张表的权限赋给一个用户的操作。正常情况下,我们希望写一个类似GrantPermission("dbo.Blogs","guest",Permission.Select);的方法。

    首先,我们创建一个MigrationOperation的子类,即一个自定义操作。除了实现IsDestructiveChange这个属性别的不需要任何操作。

    using System.Data.Entity.Migrations.Model;
     
    namespace ExtendingMigrations.Migrations
    {
      public enum Permission
      {
        Select,
        Update,
        Delete
      }
     
      public class GrantPermissionOperation : MigrationOperation
      {
        public GrantPermissionOperation(string table, string user, Permission permission)
          : base(null)
        {
          Table = table;
          User = user;
          Permission = permission;
        }
     
        public string Table { get; private set; }
        public string User { get; private set; }
        public Permission Permission { get; private set; }
     
        //是否为破坏性的修改
        public override bool IsDestructiveChange
        {
          get { return false; }
        }
      }
    }
    

    下面,我们来写一个扩展方法以实现我们想要的功能。我们使用IDbMigration接口,这个接口让我们可以有权限操作DbMigration中不可见的API。(比如下面migration,本身没有AddOperation操作【fuck,这是怎么实现的!】,但是,强制转换为IDbMigration的时候就有了)

    using System.Data.Entity.Migrations;
    using System.Data.Entity.Migrations.Infrastructure;
     
    namespace ExtendingMigrations.Migrations
    {
      public static class Extensions
      {
        public static void GrantPermission(this DbMigration migration, string table, string user, Permission permission)
        {
          ((IDbMigration)migration)
            .AddOperation(new GrantPermissionOperation(table, user, permission));
        }
      }
    }
    

    你可以把上面的扩展方法作为普通的方法写在GrantPermissionOperation类中,但是,假如像我这样使用了扩展方法,那么在类中我们就有更漂亮的写法。如下:

    namespace ExtendingMigrations.Migrations
    {
        using System;
        using System.Data.Entity.Migrations;
     
        public partial class GrantGuestPermissions : DbMigration
        {
            public override void Up()
            {
              this.GrantPermission("dbo.Blogs", "guest", Permission.Select);
            }
     
            public override void Down()
            {
            }
        }
    }
    

    为我们的操作创建SQL

    如果我们现在就调试运行我们的新的数据迁移类,那么肯定会出现异常。因为默认的SQL生成器不知道我们的操作流程。不过,我们可以从已经存在的migrator(迁移器?可以这样叫么?)中继承然后将新的SQL生成逻辑添加到我们的操作中。

    using System.Data.Entity.Migrations.Model;
    using System.Data.Entity.Migrations.Sql;
     
    namespace ExtendingMigrations.Migrations
    {
      public class MySqlServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator
      {
        protected override void Generate(MigrationOperation migrationOperation)
        {
          var operation = migrationOperation as GrantPermissionOperation;
          if (operation != null)
          {
            using (var writer = Writer())
            {
              writer.WriteLine(
                "GRANT {0} ON {1} TO {2}",
                operation.Permission.ToString().ToUpper(),
                operation.Table,
                operation.User);
     
              Statement(writer);
            }
          }
        }
      }
    }
    

    注意上面的代码中,Generate方法被我们重写了,但是,我们却没有执行base.Generate(..);方法,因为父类的方法不知道如何处理这个逻辑,所以即使调用也会报异常。而且,也只有在我们默认的SQL生成器不知道如何处理我们自定义SQL的时候才会调用我们的Generate(MigrationOperation)方法。

    最后,我们需要在数据迁移配置(migrations configuration)中注册我们新的SQL生成器:

    namespace ExtendingMigrations.Migrations
    {
      using System.Data.Entity.Migrations;
     
      internal sealed class Configuration : DbMigrationsConfiguration<ExtendingMigrations.BloggingContext>
      {
        public Configuration()
        {
          AutomaticMigrationsEnabled = false;
     
          // Register our custom generator
          SetSqlGenerator("System.Data.SqlClient", new MySqlServerMigrationSqlGenerator());
        }
      }
    }
    

    测试

    在我们VS的包管理控制台中输入Update-Database -Script,会输出更新数据库(对数据库进行数据迁移)时要执行的SQL脚本,其如下:

    GRANT SELECT ON dbo.Blogs TO guest
     
    INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
    VALUES ('201302272012532_GrantGuestPermissions', 'ExtendingMigrations.Migrations.Configuration', 0x1F8B0800000..., '6.0.0-alpha3-20222')
    
    
  • 相关阅读:
    打开服务器的文档
    笔记
    centos6.5 编译openssl-1.1.1k
    搭建自己的低代码平台
    防火墙ACL配置自动化
    防火墙ACL配置自动化
    【树莓派】读取新大陆(newland)USB条码扫描器数据
    解决eclipse或sts闪退的办法(转)
    浅谈数据库迁移类项目功能测试的基本思路
    ATM取款机优化需求的用例设计
  • 原文地址:https://www.cnblogs.com/ensleep/p/5060120.html
Copyright © 2020-2023  润新知