废话

话说当年,在一个春光明媚的晌午,邂逅了迷人的丁香姑娘,从此拜倒在了她的石榴裙下,至今不能自拔,这位丁香姑娘就是ORM思想。

所谓ORM思想,我的理解就是根据一定的规则,把程序中的对象数据库中的关系数据相互映射转换。在当年之前,我用ADO.NET编写数据持久层,拼接T-Sql语句,这是一个相当繁琐的过程,而且针对不同的数据库,还要调整T-Sql语句。记得,第一个网站上线的时候,数据库改成了MySql的,为了适配MySql,我改了两天的Sql语句。现在每每想起,都不禁摇头哂笑。

ORM思想如何做到屏蔽各大数据库之间的差异呢?程序对象和关系数据之间的相互映射是基于一定的规则的,只要制定好规则,它们的转换就易如反掌。那么,规则怎么制定,谁来制定?规则制定可以简单理解为翻译,即把程序设计语言翻译成数据库语言(T-Sql), 无论什么数据库都兼容最基本的T-Sql语法,外加各自的一些差异。这样不同的程序设计语言就可以针对不同的数据库开发对应的规则。通常数据库厂商或者团队或者社区都会维护这些规则,当然也可以自己DIY。

实现了ORM思想的框架也是琳琅满目,例如:

EntityFramework:.Net程序员最熟悉的啦,由Microsoft支持。

Hibernate:很流行,各种版本的都有。

Dapper:最清凉的,好像就几百K。

And so on……

CodeFirst+MySql使用姿势

如题,本文是使用EntityFramework6框架的感悟(爬坑泪水),以飨同道。

自从学会了EF的基本使用,都是在别人开发好了项目框架上做CRUD,很多细节没有体会到,这次正好有个机会亲自搭建项目框架,深入体会个中奥妙。

配置:win10+vs2015community+.NetFramework4.5.2+MySql5.6

一、基本操作
1、创建控制台项目:CodeFirstDemo。

2、通过NuGet包管理器安装:EntityFramework6.1.3、MySql.Data.Entity6.9.8
检查项目的引用中是否有下图所示的四个引用

添加新建项→ADO.NET实体对象模型(命名MyContext)→空CodeFirst模型。该模型会自动在app.config中添加连接字符串:

<connectionStrings>
<add name="MyContext" connectionString="data source=(LocalDb)\MSSQLLocalDB;initial catalog=CodeFirstDemo.MyContext;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>

很显然这是默认的MSSqlServer的配置,稍后再来修改。

3、在MyContext中,反注释掉MyEntities及其实现类代码。

public virtual DbSet<MyEntity> MyEntities { get; set; }
public class MyEntity
{
public int Id { get; set; }
public string Name { get; set; }
}

这就是程序中的对象。

根据CodeFirst的约定:Id会被设置为主键。

更多约定详见msdn(https://msdn.microsoft.com/zh-cn/data/jj679962)。

4、如何把MyEntity映射到MySql数据库中?。 三步走:

打开vs工具

第一步: 在控制台中输入Enable-Migrations(启动迁移)。注意:默认项目一定要是模型所在的项目。

此时项目中会自动生成Migration文件夹

下面我来解释下Configuration.cs类

这是迁移的配置类,在最后执行迁移的时候会执行这个类。

它有两个方法:

a、Configuration():无参的构造方法。可以在这里配置迁移之前的操作,后文再详细描述。

b、Seed(MyContext):void:这个方法是在执行迁移成功之后执行,一般用来初始化数据库用的。例如:我要在生成数据库的时候就初始化一条记录。

protected override void Seed(CodeFirstDemo.MyContext context)
{
// This method will be called after migrating to the latest version. // You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
context.MyEntities.AddOrUpdate(new MyEntity()
{
Name = "张三"
});
context.SaveChanges();
}

第二步:在控制台输入:Add-Migration InitModel。(InitModel:为本次迁移起个名字)

此时在项目的Migration文件夹中会自动生成迁移记录文件,文件名以“当前时间_本次迁移的名字”作为类名。

记录文件有一个设计类和一个资源类和一个迁移具体操作的方法。

设计类:本次迁移的具体记录。自动生成、维护。

资源类:默认架构和目标。自动生成、维护。

具体操作:该类维护Up()和Down()两个方法,分别用于升级和降级。有时候需要我们自己定制它,因此要理解它,可以参考我写的注释。

public partial class InitModel : DbMigration
{
/// <summary>
/// 本次迁移执行的具体操作,即升级数据库。
/// </summary>
public override void Up()
{
//创建架构为"dbo",表名为”MyEntities"的数据库表。
CreateTable(
"dbo.MyEntities",
c => new
{
Id = c.Int(nullable: false, identity: true),//Id,int类型,不可为空,标识列(自动增长)。
Name = c.String(),//Name,string类型
})
.PrimaryKey(t => t.Id);//设置主键为Id }
/// <summary>
/// 以后如果回滚数据库,那么会执行此降级方法。
/// </summary>
public override void Down()
{
DropTable("dbo.MyEntities");//删除架构为"dbo",表名为”MyEntities"的数据库表。
}
}

第三步:在控制台输入Update-DataBase –script。生成Sql脚本。(在迁移过程中出现奇葩问题的时候,就生成sql脚本检查一下吧。)

CREATE TABLE [dbo].[MyEntities] (
[Id] [int] NOT NULL IDENTITY,
[Name] [nvarchar](max),
CONSTRAINT [PK_dbo.MyEntities] PRIMARY KEY ([Id])
)
CREATE TABLE [dbo].[__MigrationHistory] (
[MigrationId] [nvarchar](150) NOT NULL,
[ContextKey] [nvarchar](300) NOT NULL,
[Model] [varbinary](max) NOT NULL,
[ProductVersion] [nvarchar](32) NOT NULL,
CONSTRAINT [PK_dbo.__MigrationHistory] PRIMARY KEY ([MigrationId], [ContextKey])
)
INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'201601021118458_InitModel', N'CodeFirstDemo.Migrations.Configuration', 0x1F8B0800000000000400CD57DB6E1B37107D0FD07F20F8D400B6E8CB4B6AAC12B8B25D18896C23EBE49DDA1DC94479D9925C43FB6D79C827F5173AD4DE7725457683A2102068676786670EE70CA9BFBF7D8F3EAC9524CF609D307A4A4F272794804E4C2AF46A4A73BF3C7E473FBCFFE54D749DAA35F95AFB9D073F8CD46E4A9FBCCF2E1873C91328EE264A24D638B3F493C428C653C3CE4E4E7E63A7A70C3005C55C84449F73ED8582CD033ECE8C4E20F3399773938274951DDFC49BACE48E2B70194F604A67E87123ACF357A00C259752700411835C52C2B5369E7B8478F1C541ECADD1AB384303978F4506E8B7E4D24105FDA2753FB48A93B350056B03EB5449EEBC512F4C787A5ED1C286E1AF229736B42171D748B02F42D51BF2A6745E94264A868B5DCCA40D8E036E2775C411E9D98F9A36C06E091F7C9F4B9F5B986AC8BDE5F2883CE40B29928F503C9A3F414F752E65171DE2C3773D039A1EACC9C0FAE2332C2BCCB72925AC1FC786814D5827A6ACE656FBF3334AEE7071BE90D06C7EA7F2D81B0B7F8006CB3DA40FDC7BB03AE4808A2BB677ADF05DAF86DD869AA164CED79F40AFFC1352CED794DC8835A4B5A542F0450B941806799B437F9188B53B37DE4F148AE702E1369B1A2CB0F65B761515506DACAB16EAD752668CC1F71B4480A3A4C5504A6BD276CF36B00DAC56B8AC546EAD70B643E2D19C6719F2D6917C652171A5F7E3F8E56A50650E96B82DA268D0362B6117F0150CDE76E5C03D5FF0B073B3548DDCDA4DD84170BDCE88E7A1025ADAEB90F0BB0CDBAECD618A96BF1B2C49611B6FAA83064B67108C4237F3964B6EB7486A6664AEF42E59EE8B2E45D28D2F2DE30C111B601FF2C346040D86C390F27DBD3A7469566F7A76D09B51D5272F39A3AAC6295D28416A9E451A9A262E9C0735090E93F82F399302EB6D1DE65C8B25385FCE4F8A7DFD6E70D6FD7FCE1DE65C2A0F3C7CFEF3434004567F38E64767C4E1735F3F739B3C71FBABE2EBB7DD4CFF76B68FA7CF41F3BBD83BBDCB469CD2748177A7C7126877F0BF72BA8F9511B1EE1D2FBA0227566D8A70E3D39084966B93D63EB77A696AC2B1BC2EA2DA65B01F73F03C45962EAD174B9E787C9D80739BF3F82B9739BA5CAB05A4B7FA3EF759EE2F9D03B590BDD32C62FBD7DF1C617DCCD17D169EDCCF2801610A2C01EEF5EFB9906983FB66DC8FBB528486A99A1C51E17D04D3AD8A26D39DD10726AAE8BB820C7490C823A84C623277AF63FE0CAFC18697914FB0E249510FB8DD497EBC117DDAA32BC157962B57E568E3C3FF1616FEB8BCFF07A10C3040EA0C0000 , N'6.1.3-40302')

如上图所示:第一段创建表MyEntities,是我们的目标,这没错,很正常。

第二段:创建表_MigrationHistory,这是什么鬼。其实这就是EF6框架用来维护模型的表,

[MigrationId]:遍号,主键,存储设计类中Id,其实就是本次迁移记录的名称。

[ContextKey]:标记当前上下文的识别码,主键,因为CodeFirst支持多个上下文实例,所以用这个字段来标记。

[Model]:模型,当前模型的具体描述,加密了。

[ProductVersion]:EF框架的版本号。

EF6框架通过这张表具体记录每次迁移变化,也是通过这张表来检查程序中的对象和数据库中的关系是否一致。

下面继续在控制台输入:Update-DataBase –verbose(或者-v)。更新数据库,并且查看执行的具体sql语句。

结果:

哦,通过查看错误信息,我们可以知道原来是当前配置的是MSSqlServer,而我本机又没有安装MSSqlServer数据库实例,所以当然连接不上了。我们的目标是MySql数据库,所以就要修改App.config中连接字符串了。

打开App.config:

找到连接字符串:

<connectionStrings>
<add name="MyContext" connectionString="data source=(LocalDb)\MSSQLLocalDB;initial catalog=CodeFirstDemo.MyContext;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>

修改为MySql的连接字符串:

<connectionStrings>
<add name="MyContext" connectionString="Data Source=127.0.0.1;port=3306;Initial Catalog=CodeFirstDemoDb;user id=root;password=1234;" providerName="MySql.Data.MySqlClient"/>
</connectionStrings>

再次在控制台输入:Update-DataBase –verbose。

这是因为当前的Sql生成器依然是MSSqlServer,那么如何启动MySql的Sql生成器呢?

在Migration文件夹中的配置类Congifuration的构造方法中:

public Configuration()
{
AutomaticMigrationsEnabled = false;
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());//设置Sql生成器为Mysql的
}

再次在控制台输入:Update-DataBase –verbose。

我擦泪!!!

这是MyEntity.Name属性为string类型,直接映射到MySql中的话是longtext,而MySql支持最大长度为767bytes。

可以用DataAnnotations(数据注释)方式,配置MyEntity.Name属性的映射规则:(还有一种方式是FluntApi,之后再介绍)

public class MyEntity
{
public int Id { get; set; }
[MaxLength()]
public string Name { get; set; }
}

但是到仅仅这样还不够,因为上下文配置还是默认的MSSqlServer的,_MigrationHistory表也有字段是string类型的,还会出现该错误。我们还要在MyContext类上通过特性标记上下文使用MySql的配置。

[DbConfigurationType(typeof(MySqlEFConfiguration))]
public class MyContext : DbContext
{
……

因为修改了模型,所以要重新生成迁移,在控制台输入:Add-Migration InitModel –Force (表示强制执行,即更新。或者简写-f),然后再输入Update-Database –v。

PM> add-migration InitModel -f
Re-scaffolding migration 'InitModel'. PM> update-database -v
Using StartUp project 'CodeFirstDemo'.
Using NuGet project 'CodeFirstDemo'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Target database is: 'CodeFirstDemoDb' (DataSource: 127.0.0.1, Provider: MySql.Data.MySqlClient, Origin: Configuration).
Applying explicit migrations: [201601021247042_InitModel].
Applying explicit migration: 201601021247042_InitModel.
create table `MyEntities` (`Id` int not null auto_increment ,`Name` nvarchar() ,primary key ( `Id`) ) engine=InnoDb auto_increment=
create table `__MigrationHistory` (`MigrationId` nvarchar() not null ,`ContextKey` nvarchar() not null ,`Model` longblob not null ,`ProductVersion` nvarchar() not null ,primary key ( `MigrationId`) ) engine=InnoDb auto_increment=
INSERT INTO `__MigrationHistory`(
`MigrationId`,
`ContextKey`,
`Model`,
`ProductVersion`) VALUES (
'201601021247042_InitModel',
'CodeFirstDemo.Migrations.Configuration',
0x1F8B0800000000000400CD57DB6EDB38107D2FD07F20F89C9A4E822EBA81DC22759222D83A09AAB4EFB4347688F2A29254607F5B1FFA49FD851D5A77C9769DECA2280C181639333C73386746FEF9FD47F46EA5247904EB84D1137A3C1A53023A31A9D0CB09CDFDE2D51BFAEEEDCB17D165AA56E44B65771AECD053BB097DF03E3B63CC250FA0B81B299158E3CCC28F12A3184F0D3B198FFF66C7C70C3004C55884449F72ED8582CD033E4E8D4E20F3399733938274E53AEEC49BA8E4862B70194F6042A7687125ACF317A00C25E752700411835C50C2B5369E7B8478F6D941ECADD1CB38C3052EEFD719A0DD824B0725F4B3C6FCD02CC627210BD63856A192DC79A39E18F0F8B4A485F5DD9F452EAD6943E22E9160BF0E596FC89BD0D9BA58A2A47FD8D954DA60D8E37654791C91CEFA515D06582DE183FBB9F4B9858986DC5B2E8FC85D3E9722F907D6F7E62BE889CEA56CA3437CB8D759C0A53B6B32B07EFD091625E6EB9412D6F5637DC7DAADE5536473ADFDE909253778389F4BA82FBF9579EC8D850FA0C1720FE91DF71EAC0E31A0E48AED3D2B7C57A761B5A1662899F1D547D04BFF806A1AA34AAEC40AD26AA544F0590B94183A799B43F79088353737BC4F148AE702E1D6971A5660E5B7DC2A2AA0BC58571ED4CDA5881883EF168800474983A190D6A8A99E6D606B588D7059A1DC4AE16C87C4A319CF32E4AD25F97285C4A5DE5FC54F57832A62B0C46D11458DB63E09AB802FA1B7DB9603F77CCEC3CD4D5335306B2E6107C1D539039EFB0A6868AF5CC2EFC26DBB36FB211AFEAE30258565BCC90E6A2CAD463070DDF45B2EB9DD22A9A991B9D2BB64B9CFBB1049DBBF58194688580F7B9F1F3620A8D71CFA94EFABD5BE497D7A5DB3BDDA8CCA3A79CA8C2A0BA730A104A97914695134F137390AFBA3CDCFA91498706331E35A2CC0F9A281D2D7A3BF7AB3EECF993BCCB9541E387C7EFB101081D45FB6F9C18C38BCEFEB476E93076E879DBF09FA5FDBFCB0111DD4CAD77B1B795193139ACEF135EABE00DA9E01CF6CF4439144ACFDBA175D8013CB264478F9D39084EA6B825636D77A612AEE31BD36A2CAA4773533F03C4596CEAD170B9E78DC4EC0B9CD68FEC2658E26976A0EE9B5BECD7D96FB73E740CD6567B0456CFFF99B69D6C51CDD66E1C9FD1F29204C8129C0AD7E9F0B99D6B8AF86A5B92B442898B2DE1115BE9A60B8E5BA8E7463F481814AFA2E20031DD4720F2A9318CCDDEA983FC273B0E17BC94758F2645DB5BADD417E7D115DDAA30BC197962B57C668FCC35F1816FEC3BCFD175F3BFF74F50C0000,
'6.1.3-40302');
Running Seed method.

最后执行了Seed方法,我们去检查下MySql数据库,看到如下图所示

最终执行了Seed方法,初始化了这么一条数据。

如此,使用CodeFirst+MySql的基本姿势已经结束了。

以后更新模型的话,只要走第二步和第三步就可以了。

使用这种姿势遇到了不少坑,都记录到下面这篇博客中。

EF6(CodeFirst)+MySql开发脱坑指南的更多相关文章

  1. EF6(CodeFirst)+MySql开发遇到的坑

    最近一不小心偷个懒就已经过了好几个月了,真是惭愧惭愧,出来混终究是要还的,我还是把”脱坑指南“写完吧,-_-~~.点我打开上篇博客 0x001.架构名”dbo”の殇 坑之首也,当提架构名,在mssql ...

  2. CodeFirst+MySql开发

    CodeFirst+MySql开发简单入门 记录一下使用Mysql进行EF Codefirst方式开发的简单过程. 0.准备工作 安装MySql,mysql-connector-net,mysql-f ...

  3. C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式

    C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...

  4. Harmony OS 开发避坑指南——源码下载和编译

    Harmony OS 开发避坑指南--源码下载和编译 本文介绍了如何下载鸿蒙系统源码,如何一次性配置可以编译三个目标平台(Hi3516,Hi3518和Hi3861)的编译环境,以及如何将源码编译为三个 ...

  5. Taro 开发踩坑指南 (小程序,H5, RN)

    Taro 开发踩坑指南 (小程序,H5, RN) css taro 如何展示多行文本省略号 https://www.cnblogs.com/xgqfrms/p/12569057.html UI 设计稿 ...

  6. 大数据 SQL Boy 脱坑指南

    不可否认的是 SQL 是一个伟大的发明,它让增删改查的操作更加地便捷化,而且 SQL 的学习成本相对其他编程语言来说较低,被逼到会写 SQL 的运营和产品我都见过不少... 大数据行业跟 SQL 更是 ...

  7. Flutter 开发填坑指南

    引言 第一次在使用Flutter是在Ubuntu机器上,但是因为Android Studio还有Sdk配置问题,flutter doctor总是在这一步报错...最近又在win10上配了一下环境(真香 ...

  8. 微信小程序开发填坑指南V1

    近期用了一星期的时间,开发了一个小程序.小程序名称是:小特Jarvis,取自钢铁侠的管家. 后台采用C#编写,WebAPI接口.其实开发时间并不多,小程序本身提供的API,相比公众号的API来说,已经 ...

  9. Harmony OS 开发避坑指南——DevEco Device Tool 安装配置

    Harmony OS 开发指南--DevEco Device Tool 安装配置 本文介绍如何在Windows主机上安装DevEco Device Tool工具. 坑点总结: 国内部分网络环境下,安装 ...

随机推荐

  1. Git远程操作

    Git远程操作 // */ // ]]>   Git远程操作 Table of Contents 1 Git远程命令概览 2 Git远程仓库与本地仓库的关系图 3 git clone 4 git ...

  2. windows下搭建scrapywindows 7 (64) + python 3.5 (64)

    说明 之前在 window 10 (64) + python 3.5 (64) 环境下就已经成功安装了 scrapy,当然也费了不少周折. 由于近日将系统换回 windows 7 (64),再安装 s ...

  3. 【转】Crontab定时任务配置

    原文出处:http://www.cnblogs.com/kerrycode/p/3238346.html CRONTAB概念/介绍 crontab命令用于设置周期性被执行的指令.该命令从标准输入设备读 ...

  4. 设置secureCRT的鼠标右键为弹出文本操作菜单功能

    options菜单下的 global options 页面的 terminal 中的 mouse 子菜单对 paste  on  right button 的选项取消勾选即可.

  5. 编辑器sublime text3和插件package control、Sidebar Enhancements插件安装

    (1)编辑器sublime text3的安装:选择自己需要的版本下载安装:http://www.sublimetext.com/3 (2)package control插件安装:https://pac ...

  6. Log

    Public Shared Sub WriteLog(ByVal FormID As String, ByVal ex1 As Exception) 'log信息 Dim loginfo As Str ...

  7. 构建angular项目

    1. 安装yo与gulp bower $ npm install -g yo $ npm install -g gulp bower 2. 快速创建     $ npm install -g gene ...

  8. pl/sql中文乱码问题解决

    最近用pl/sql连我们公司的数据库,发现表里的中文数据都是“???”,上网查了一下,发现是数据库的编码格式和pl/sql的编码格式不统一造成的. 解决方法非常简单,只要创建一个系统环境变量:NLS_ ...

  9. shell编写mysql备份工具

    如需转载,请经本人同意. 这是之前写的一个备份脚本,调用的备份工具是xtrabackup 编写思路是:每周一全备份,备份后提取lSN号,对备份文件进行压缩,其余时候在LSN的基础上进行增量备份,并对3 ...

  10. Mac OS X 访问 Windows 共享文件夹

    Mac OS X 访问 Windows 共享文件夹 mac没有网络邻居,但可以使用finder访问局域网中windows共享的文件 1.点击 Finder 前往菜单中的「前往服务器」(或快捷键 com ...