本文主要介绍如何使用CodeFirst模式来新建并更新数据库

在使用Entity Framwork的三种方式(ModelFist、DBFirst、CodeFirst)中,CodeFirst方式书写的代码最为干净。

至于CodeFist方式的详细优缺点请各位读者自行搜索,这里不多赘述。

1. 使用CodeFirst方式创建数据库

我们新建一个控制台项目,项目中添加两个Model:Author和Blog以及DbContext。 DbContext的添加方式如下:

项目上右键->添加->新建项->ADO.NET Entity Data Model->Empty Code First model

项目代码如下:

 //默认生成的数据表名为类名+字母s,这里使用TableAttribute来指定数据表名为T_Authors
[Table("T_Authors")]
public class Author
{
public int Id { set; get; }
public string Name { set; get; }
/*
此处定义了Blog类型的属性,所以要确保Blog类中至少要有一个表示主键的字段,即public int Id { set; get; }。
      否则在生成数据表时会报错:"EntityType 'Blog' has no key defined. Define the key for this EntityType.
    Blogs: EntityType: EntitySet 'Blogs' is based on type 'Blog' that has no keys defined."
    */
public virtual ICollection<Blog> Blogs { set; get; }
} [Table("T_Blogs")]
public class Blog
{
public int Id { set; get; }
public string Title { set; get; }
public DateTime Time { set; get; }
public int AuthorId { set; get; }
public virtual Author Author { set; get; }
} public class MyDbContext: DbContext
{
public MyDbContext()
: base("name=MyDbContext")
{
}
//DbContext会根据配置文件中connectionStrings指定的数据库名称来建立数据库
//DbContext根据DbSet属性的类型来创建数据表,这里指定了Author类型的属性,所以会生成T_Authors数据表
public virtual DbSet<Author> Authors { set; get; }
}

CodeFirst方式会根据配置文件中的配置生成数据库,这里小编使用的是MYSQL数据库,配置文件如下:

 <!--EF for MYSQL-->
 <entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" />
</providers>
</entityFramework>
<connectionStrings>
<add name="MyDbContext" connectionString="server=localhost;port=3306;database=EF;uid=root;password=root" providerName="System.Data.MySqlClient" />
</connectionStrings>

PS:小编使用的是EF6和MYSQL数据库,所以要在项目中添加对Mysql.Data.Entity.EF6以及EntityFrameword 6.0的引用。

到此,我们已经完成生成数据库的工作,接下来在Main方法中写两行代码:

 using (var db = new MyDbContext())
{
db.Authors.Add(new Author() { Name = "xfh" });
db.SaveChanges();
}

运行程序,我们会发现EF已经为我们建立了数据库,数据库名称为EF(在配置文件中指定)以及数据表T_Authors。

虽然我们没有为DbContext添加Blog类型的属性,但依然创建了数据表T_Blogs,这是因为在Author类中定义了Blog类型的属性,若我们注释掉

public virtual ICollection<Blog> Blogs { set; get; } ,删除数据库重新生成就会发现不在生成T_Blogs表。在生成T_Authors表的同时,会生成一张名为_migrationhistory表,这张表用于记录我们对于数据库的更新日志,表中的MigrationId字段的值是我们每次执行Migration时所生成的文件名,根据该字段的值我们可以使用命令 Update-Database -TargetMigration:MigrationIdValue 来将数据库恢复到MigrationIdValue所对应的Migration状态,和Git版本控制有点儿像,但这里若将数据库回滚到以前的版本会导致数据的丢失,并且_migrationhistory表也会删除所记录的当前Migration信息。

2. 更新数据库(Code Fist Migration)

现在,我们给Author类增加字属性Email,代码如下:

    [Table("T_Authors")]
public class Author
{
public int Id { set; get; }
public string Name { set; get; }
public string Email { set; get; }
public virtual ICollection<Blog> Blogs { set; get; }
}

此时,再次运行该应用程序,则将抛出异常

An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll
The model backing the 'MyDbContext' context has changed since the database was created. Consider using Code First Migrations to
update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

异常信息中提示我们数据库创建之后model发生了变化,所以我们需要对数据库进行更新使二者保持一致才能运行程序。

2.1 启用迁移

对于首次迁移需要启用迁移,具体方法是在Packge Manager Console中输入Enable-Migrations命令即可。

命令运行完毕之后我们会看到命令行中的提示信息

这里我们只是启用了迁移,但不是自动迁移。从提示信息中我们可以看到若要启用自动迁移则要删除Migrations文件夹并在Packge Manager Console中输入

Enable-Migrations –EnableAutomaticMigrations命令或者在Migrations文件夹的Configuration.cs文件中设置AutomaticMigrationsEnabled属性为true即可。

Enable-Migrations命令运行完毕之后会在项目中生成如下文件:

Configuration文件 我们可以在此文件中针对上下文配置迁移行为。

InitialCreate文件   因为我们事先让 Code First 自动创建了一个数据库,这个迁移文件中的代码表示数据库中已创建的对象。该文件文件名包含时间戳,这对于排序十分有帮助。如果尚未创建数据库,则不会将此 InitialCreate 迁移添加到项目中。而是,首次调用 Add-Migration 时,用于创建这些表的代码将为新迁移搭建基架。

2.2 更新数据库

启用迁移之后,在Packge Manager Console中继续输入Update-Database命令来更新数据库,但会发现更新失败。

通过上面的提示信息我们可以知道,要想更新数据库需要启用自动迁移或者使用Add-Migration命令来创建迁移文件。

2.2.2 基于代码的迁移

我们在Packge Manager Console中输入命令Add-Migration AddEmail,命令运行完毕后我们会发现Migrations文件夹下已经创建了_AddEmail文件,文件内容如下:

 public partial class AddEmail : DbMigration
{
public override void Up()
{
//注意,这里数据表的名称是dbo.T_Blogs和dbo.T_Authors而不是我们指定的
//T_Blogs和T_Authors,我们可以把数据表名称改为T_Blogs和T_Authors
//数据表以dbo开头貌似是SQL SERVER中的命名方式,这里小编使用的是MYSQL
CreateTable(
"dbo.T_Blogs",
c => new
{
Id = c.Int(nullable: false, identity: true),
Author_Id = c.Int(),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.T_Authors", t => t.Author_Id)
.Index(t => t.Author_Id); AddColumn("dbo.T_Authors", "Email", c => c.String(unicode: false));
} public override void Down()
{
DropForeignKey("dbo.T_Blogs", "Author_Id", "dbo.T_Authors");
DropIndex("dbo.T_Blogs", new[] { "Author_Id" });
DropColumn("dbo.T_Authors", "Email");
DropTable("dbo.T_Blogs");
}
}

我们可以看到Up方法中调用了AddColumn方法来向数据库中添加Email字段。这时我们在Packge Manager Console中输入命令Update-Database命令(也可以使用Update-Database -Verbose命令,该命令可以使我们看到SQL语句的执行过程,注意-Verbose和-Database之间有个空格)并运行,可以看到命令成功执行,然后到数据库中查看数据表T_Authors发现表中已经添加字段Email,同时数据表__migrationhistory中对于我们的此次更新进行了记录。

对于上述代码我们可以进行简化:

public partial class AddEmail : DbMigration
{
public override void Up()
{
AddColumn("T_Authors", "Email", c => c.String(unicode: false));
} public override void Down()
{
DropColumn("T_Authors", "Email");
}
}

我们也可以直接通过创建迁移文件来更新数据库而不修改Model。如:

通过命令Add-Migration addAge来创建一个新的迁移文件,代码如下:

public partial class AddAge : DbMigration
{
public override void Up()
{
AddColumn("T_Authors", "Age", c => c.Int(nullable: false,defaultValue:));
} public override void Down()
{
DropColumn("T_Authors", "Age");
}
}

然后运行命令Update-Database,我们会发现数据库T_Authors表中创建了字段Age。虽然成功的更新了数据库,但会导致程序中的Model和数据表不匹配。

2.2.2  自动迁移

启用自动迁移的方法前文已经陈述。在启用自动迁移之后,我们再修改Model文件,只需执行Update-Database命令即可完成对数据库的更新。

最后再补充一点,在创建数据库之后若修改TableAttribute和ColumnAttribute的值,那么在执行程序时EF会按照TabelAttribute和ColumnAttribute中指定的值和数据库进行匹配,但数据库中并不存在我们新指定的数据表和字段,这会导致程序报错。若我们修改了TableAttribute和ColumnAttribute的值,然后再使用Update-Database命令来更新数据库,数据库会新建一张有TableAttribute指定名称的数据表。

参考文章:

自动化 Code First 迁移

What is Code-First

Code First 迁移

版权声明

本文为作者原创,版权归作者雪飞鸿所有。
转载必须保留文章的完整性,且在页面明显位置处标明原文链接

如有问题, 请发送邮件和作者联系。

使用CodeFirst创建并更新数据库的更多相关文章

  1. EF CodeFirst使用Nuget更新数据库

    常用命令: 1.开启迁移 Enable-Migrations -EnableAutomaticMigrations 2.添加一条迁移记录 Add-Migration AddMigration001 3 ...

  2. .net:Code First 创建或更新数据库

    控制台输入命令: 切换到项目的project.json 文件所在文件 dotnet ef migrations add XXX dotnet ef database update Visual Stu ...

  3. Android创建和使用数据库

    一.关系型数据库SQLIte         每一个应用程序都要使用数据.Android应用程序也不例外,Android使用开源的.与操作系统无关的SQL数据库-SQLite. SQLite第一个Al ...

  4. EF core (code first) 通过自定义 Migration History 实现多租户使用同一数据库时更新数据库结构

    前言 写这篇文章的原因,其实由于我写EF core 实现多租户的时候,遇到的问题. 具体文章的链接: Asp.net core下利用EF core实现从数据实现多租户(1) Asp.net core下 ...

  5. 使用EF CodeFirst 创建数据库

    EntityFramework 在VS2015添加新建项时,选择数据->ADO.NET 实体数据模型,有一下选项 来自数据库的EF设计器,这个就是我们最常用的EntityFramework设计模 ...

  6. 使用CodeFirst创建数据库

    1.新建一个类库项目 2.右键管理Nuget程序包,搜索EntityFramework.然后安装 3.新建一个类,然后引用 using System.Data.Entity; 然后写类初始化方法(ba ...

  7. EF Code-First(Oracle)通过Migration来更新数据库的表的字段

    关于Oracle中使用Entity Framework 6.x Code-First方式开发,请参考博客(菩提树下的杨过)https://www.cnblogs.com/yjmyzz/p/how-to ...

  8. EF CodeFirst 创建数据库

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精    话说EF支持三种模式:Code First   M ...

  9. 支持“***Context”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269)。

    在用VS进行MVC开发的过程中遇到如下问题: 支持“***Context”上下文的模型已在数据库创建后发生更改.请考虑使用 Code First 迁移更新数据库(http://go.microsoft ...

随机推荐

  1. 学习笔记:Java的一些基础小知识之JVM与GC

      一.JVM是什么 Java虚拟机(英语:Java Virtual Machine,缩写为JVM),又名爪哇虚拟器,一种能够运行Java bytecode的虚拟机,以堆栈结构机器来进行实做.最早由太 ...

  2. PostgreSQL 9.3发布

    9月9日,PostgreSQL全球开发组宣布了9.3版发布的消息.从2010年9.0版开始,PostgreSQL已经连续四个版本稳定地按时在每年9月中旬发布,从一个侧面也显示了开发团队的强大实力. 9 ...

  3. 通杀所有系统的硬件漏洞?聊一聊Drammer,Android上的RowHammer攻击

    通杀所有系统的硬件漏洞?聊一聊Drammer,Android上的RowHammer攻击 大家肯定知道前几天刚爆出来一个linux内核(Android也用的linux内核)的dirtycow漏洞.此洞可 ...

  4. 基础知识漫谈(2):从设计UI框架开始

    说UI能延展出一丢丢的东西来,光java就有swing,swt/jface乃至javafx等等UI toolkit,在桌面上它们甚至都不是主流,在web端又有canvas.svg等等. 基于这些UI工 ...

  5. 剑指Offer面试题:21.从上到下打印二叉树

    一.题目:从上到下打印二叉树 题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印.例如输入下图中的二叉树,则依次打印出8.6.10.5.7.9.11. 二叉树节点的定义如下,采用 ...

  6. ARM汇编指令调试方法

    学习ARM汇编时,少不了对ARM汇编指令的调试.作为支持多语言的调试器,gdb自然是较好的选择.调试器工作时,一般通过修改代码段的内容构造trap软中断指令,实现程序的暂停和程序执行状态的监控.为了在 ...

  7. SQL Server 查询分解

    标签:SQL SERVER/MSSQL SERVER/数据库/DBA/查询步骤 概述 查询步骤是很基础也挺重要的一部分,但是我还是在周围发现有些人虽然会语法,但是对于其中的步骤不是很清楚,这里就来分解 ...

  8. 如何给CentOS安装字体库

    很多时候,我们需要做一些图像生成工作(譬如验证码之类的),这时候,我们一般都需要用到系统的字体库.但事情却总非尽善人意,我们所使用的Linux操作系统无法像Windows操作系统那样足够“旗舰”,字体 ...

  9. 你可能不知道的7个CSS单位

    如果你是一名前端开发工程师,一般px和em使用频率比较高.但是今天本文的重点是介绍一些我们使用很少.甚至么有听说的单位. 一.重温em <style type="text/css&qu ...

  10. 64位Win7添加32位XP的共享打印机

    windows无法连接到打印机 错误提示0x00000214 win7 64位系统,连接32位xp上的共享打印机,提示“操作失败,错误为 0x00000214”. 使用以下方法连接就没问题了: 开始— ...