原英文版由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. Highcharts 标示区曲线图;Highcharts 对数图表;Highcharts 时间间隔图表

    Highcharts 标示区曲线图 配置 使用 yAxis.plotBands 属性来配置标示区.区间范围使用 'from' 和 'to' 属性.颜色设置使用 'color' 属性.标签样式使用 'l ...

  2. HTML通过jQuery传值赋值

    网页传值很常见,如果通过动态网页传值,我们很容易实现.但是如果静态网页传值,这个就要找资料,方法或者询问大牛们了.这个原来还真的没有做过.今天一同事需要做这个类似的功能,应该是昨天了.本来是昨天写的, ...

  3. Algorithm3: 获得一个int数中二进制位为1 的个数

    获得一个int数中二进制位为1 的个数   int NumberOfOne(int n){                  int count = 0;                  unsig ...

  4. 【cf 483 div2 -C】Finite or not?(数论)

    链接:http://codeforces.com/contest/984/problem/C 题意 三个数p, q, b, 求p/q在b进制下小数点后是否是有限位. 思路 题意转化为是否q|p*b^x ...

  5. CF910A

    题解: 简单dp dp[i]=min(dp[i-j])+1; 代码: #include<bits/stdc++.h> using namespace std; ; int n,m,dp[N ...

  6. Linux服务器静态路由配置

    转载自:点击打开链接 静态路由是在路由器中设置的固定的路由表.除非网络管理员干预,否则静态路由不会发生变化.由于静态路由不能对网络的改变作出反映,一般用于网络规模不大.拓扑结构固定的网络中.静态路由的 ...

  7. php-resque 简单的php消息队列

    摘要: 消息队列是个好东西,各种×××MQ很多.然而看一下它们的文档,你得吓尿,什么鬼,我只是想用它触发个短信接口而已. 幸好也有简单的.这次是php-resque 安装 首先这货需要在linux下跑 ...

  8. learn go function callback

    package main // 参考文档: // https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/06.7.md im ...

  9. Linux下nginx安装与配置

    部分Linux发布版的默认安装已经集成了nginx,查看方法ls /usr/local,若已有nginx文件夹说明已集成. nginx依赖库pcre与zlib,且pcre依赖于gcc与gcc-c++, ...

  10. mysql的master和slave同步方案

    同步原理 master将改变记录到二进制日志(binary log)中 slave将master的binary log events拷贝到它的中继日志(relay log) slave重做中继日志中的 ...