原英文版由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')

EF6:编写你自己的code first 数据迁移操作(睡前来一篇,翻译的)的更多相关文章

  1. EF Code First 数据迁移操作

    打开执行命令窗体 1.EF Code First创建数据库 PM> Install-Package EntityFramework 2.EF Code First数据库迁移 2.1.生成数据库 ...

  2. EF Code First 数据迁移配置

    这里我想讲清楚code first 数据迁移的两种模式,还有开发环境和生产环境数据迁移的最佳实践. 1.1 数据迁移综述 EF Code first 虽然已经有了几种不同的数据库初始化策略,但是大部分 ...

  3. 图文详解 解决 MVC4 Code First 数据迁移

    在使用Code first生成数据库后 当数据库发生更改时 运行程序就会出现数据已更改的问题  这时可以删除数据库重新生成解决 但是之前的数据就无法保留  为了保留之前的数据库数据  我们需要使用到C ...

  4. Code First 数据迁移 转

    一.为模型更改设置 Code First 数据迁移 1.工具—>库程序包管理器—>程序包管理器控制台—>输入“Enable-Migrations”  或者 Enable-Migrat ...

  5. 解决 MVC4 Code First 数据迁移 数据库发生更改导致调试失败解决方法(二)

    文章转载自:http://www.cnblogs.com/amoniyibeizi/p/4486617.html 前几天学MVC过程中,遇到更改Model类以后,运行程序就会出现数据已更改的问题导致调 ...

  6. C#+EntityFramework编程方式详细之Code First 数据迁移

    在前几篇的C#+EntityFramework编程方式中介绍了C#+EntityFramework编程方式Code First ,Model First以及Dtatabase First 等编程方式, ...

  7. Code first 数据迁移

    前段时间用到了EF,整理一下 EF ,全称Entity FramWork.就是微软以ADO.NET为基础发展的所谓ORM(对象关系映射框架,或者说是数据持久化框架). 简单说就是根据实体对象操作数据库 ...

  8. EF Core数据迁移操作

    摘要 在开发中,使用EF code first方式开发,那么如果涉及到数据表的变更,该如何做呢?当然如果是新项目,删除数据库,然后重新生成就行了,那么如果是线上的项目,数据库中已经有数据了,那么删除数 ...

  9. redis数据迁移操作

    redis客户端连接命令,分别连接旧环境中的主从redis Src目录下./redis-cli -h IP -p PORT 使用info replication 命令找出主redis使用客户端命令连接 ...

随机推荐

  1. dump相关

    命令:jmap -dump:format=b,file=/tmp/dump.hprof pid jstack -l 30087 >> text.txt

  2. 1D mesauring

              The Basics of Measure Objects   2.1 the process of 1D Edge extraction       Then, the mean ...

  3. javascript: 对象2

    数字对象Number Number 对象表示数值日期,整数或浮点数.一般情况下,你不需要担心 Number 对象,因为浏览器自动将数字文 本转换为数字类的实例. 语法 创建一个 Number 对象: ...

  4. (转载)Android学习笔记⑨——android.content.ActivityNotFoundException异常处理

    异常1:Java.lang.ClassNotFoundException 08-13 18:29:22.924: E/AndroidRuntime(1875):Caused by: Java.lang ...

  5. 构建Uber端到端技术栈的十条经验(转载)

    好文章就得分享: 一.SOA 系统设计包括若干个层面.先说顶层的系统设计原则,如 REST.SOA.由于 Uber 之前一直算一个创业公司,所以开发速度至关重要,由于微服务能够极大地促进不同组件的平行 ...

  6. vue.js 源代码学习笔记 ----- $watcher

    /* @flow */ import { queueWatcher } from './scheduler' import Dep, { pushTarget, popTarget } from '. ...

  7. IOS开发Block详细用法

    Block简介:       ios4.0系统已开始支持block,在编程过程中,blocks被Obj-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行.Blocks可以作为函数参数或者函数 ...

  8. python爬虫入门(3)-环境搭建

    下载集成包 链接:http://pan.baidu.com/s/1pKD2zBP 密码:f75b 这里采用python2.7.9   安装步骤:1.安装python2.7(默认安装即可) 2.打开“运 ...

  9. 小程序开发之scroll-view中id不能以数字开头的问题

    在实现这样的一个功能时,   调用微信小程序api发现scroll中可以通过id来实现点击菜单栏,屏幕滚动到对应的id位置 但是id不能以数字,汉字类型的 字符串开头(暂发现两种),可能博主比较笨,想 ...

  10. 【paper】KDD15 - Interpreting Advertiser Intent in Sponsored Search

    Interpreting Advertiser Intent in Sponsored Search   主要内容是搜索广告的相关性预估模型,使用learning to rank的方法.亮点在于使用了 ...