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')
EF6:编写你自己的code first 数据迁移操作(睡前来一篇,翻译的)的更多相关文章
- EF Code First 数据迁移操作
打开执行命令窗体 1.EF Code First创建数据库 PM> Install-Package EntityFramework 2.EF Code First数据库迁移 2.1.生成数据库 ...
- EF Code First 数据迁移配置
这里我想讲清楚code first 数据迁移的两种模式,还有开发环境和生产环境数据迁移的最佳实践. 1.1 数据迁移综述 EF Code first 虽然已经有了几种不同的数据库初始化策略,但是大部分 ...
- 图文详解 解决 MVC4 Code First 数据迁移
在使用Code first生成数据库后 当数据库发生更改时 运行程序就会出现数据已更改的问题 这时可以删除数据库重新生成解决 但是之前的数据就无法保留 为了保留之前的数据库数据 我们需要使用到C ...
- Code First 数据迁移 转
一.为模型更改设置 Code First 数据迁移 1.工具—>库程序包管理器—>程序包管理器控制台—>输入“Enable-Migrations” 或者 Enable-Migrat ...
- 解决 MVC4 Code First 数据迁移 数据库发生更改导致调试失败解决方法(二)
文章转载自:http://www.cnblogs.com/amoniyibeizi/p/4486617.html 前几天学MVC过程中,遇到更改Model类以后,运行程序就会出现数据已更改的问题导致调 ...
- C#+EntityFramework编程方式详细之Code First 数据迁移
在前几篇的C#+EntityFramework编程方式中介绍了C#+EntityFramework编程方式Code First ,Model First以及Dtatabase First 等编程方式, ...
- Code first 数据迁移
前段时间用到了EF,整理一下 EF ,全称Entity FramWork.就是微软以ADO.NET为基础发展的所谓ORM(对象关系映射框架,或者说是数据持久化框架). 简单说就是根据实体对象操作数据库 ...
- EF Core数据迁移操作
摘要 在开发中,使用EF code first方式开发,那么如果涉及到数据表的变更,该如何做呢?当然如果是新项目,删除数据库,然后重新生成就行了,那么如果是线上的项目,数据库中已经有数据了,那么删除数 ...
- redis数据迁移操作
redis客户端连接命令,分别连接旧环境中的主从redis Src目录下./redis-cli -h IP -p PORT 使用info replication 命令找出主redis使用客户端命令连接 ...
随机推荐
- [Web UI]对比Angular/jQueryUI/Extjs:没有一个框架是万能的
Angular不能做什么?对比Angular/jQueryUI/Extjs 框架就好比兵器,你得明白你手里拿的是屠龙刀还是倚天剑,刀法主要是砍,剑法主要是刺.对于那些职业喷子和脑残粉,小僧送你们两个字 ...
- C#中使用GUID
GUID(全局统一标识符)是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.通常平台会提供生成GUID的API.生成算法很有意思,用到了以太网卡地址.纳秒级时间.芯片ID码和许多可 ...
- 火影忍者之~鸣人 (字符串处理,strcmp)
火影忍者的男主角漩涡鸣人,因为身上封印着邪恶的九尾妖狐,无父无母的他受尽了村人的冷眼与歧视,他下定决心要成为第六代火影,让所有人都认同他的存在,火影是动漫火影忍者中主人公鸣人所在的国家的最强忍者的头衔 ...
- (MSSQL)sp_refreshview刷新视图失败及更新Table字段失败的问题解决
在近期工作中遇到一个任务,需要批量更改散布在很多Table中的某字段,同时刷新相关视图,但是在执行脚本时,发现了如下问题 更新字段问题 消息 ,级别 ,状态 ,第 行 对象'View_Simple' ...
- php-resque 简单的php消息队列
摘要: 消息队列是个好东西,各种×××MQ很多.然而看一下它们的文档,你得吓尿,什么鬼,我只是想用它触发个短信接口而已. 幸好也有简单的.这次是php-resque 安装 首先这货需要在linux下跑 ...
- js跨域详解
跨域概念:Cross-origin resource sharing
- SpringMVC札集(04)——SpringMVC传递参数
自定义View系列教程00–推翻自己和过往,重学自定义View 自定义View系列教程01–常用工具介绍 自定义View系列教程02–onMeasure源码详尽分析 自定义View系列教程03–onL ...
- Swift显示alert和promp confirmation
Swift 显示alert func Alert(title:String, msg:String)->Void{ let alert = UIAlertController(title: ti ...
- java入门学习(2)—基本数据类型
1.变量:定义变量:[数据类型] 变量名 = 赋值(这样定义的变量一般属于局部变量,放置在栈内存中): 2.标识符:可以有字母(可以使任意文字),数字,下划线,$等组成:但是不能以数字开头,不能是保留 ...
- (腾讯视频)iOS开发之视频根据url获取第一帧图片,获取任一帧图片
#import <AVFoundation/AVFoundation.h> + (UIImage*) thumbnailImageForVideo:(NSURL *)videoURL at ...