使用CodeFirst创建并更新数据库

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

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

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

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

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

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

项目代码如下:

 1 //默认生成的数据表名为类名+字母s,这里使用TableAttribute来指定数据表名为T_Authors
 2     [Table("T_Authors")]
 3     public class Author
 4     {
 5         public int Id { set; get; }
 6         public string Name { set; get; }
 7         /*
 8         此处定义了Blog类型的属性,所以要确保Blog类中至少要有一个表示主键的字段,即public int Id { set; get; }。      否则在生成数据表时会报错:"EntityType ‘Blog‘ has no key defined. Define the key for this EntityType.
 9     Blogs: EntityType: EntitySet ‘Blogs‘ is based on type ‘Blog‘ that has no keys defined."
10     */
11         public virtual ICollection<Blog> Blogs { set; get; }
12     }
13
14     [Table("T_Blogs")]
15     public class Blog
16     {
17         public int Id { set; get; }
18         public string Title { set; get; }
19         public DateTime Time { set; get; }
20         public int AuthorId { set; get; }
21         public virtual Author Author { set; get; }
22     }
23
24     public class MyDbContext: DbContext
25     {
26          public MyDbContext()
27             : base("name=MyDbContext")
28         {
29         }
30         //DbContext会根据配置文件中connectionStrings指定的数据库名称来建立数据库
31         //DbContext根据DbSet属性的类型来创建数据表,这里指定了Author类型的属性,所以会生成T_Authors数据表
32         public virtual DbSet<Author> Authors { set; get; }
33     }

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

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

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

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

1 using (var db = new ManagerDb())
2 {
3     db.Authors.Add(new Author() { Name = "xfh" });
4     db.SaveChanges();
5 }

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

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

public virtual ICollection<Blog> Blogs { set; get; } ,删除数据库重新生成就会发现不在生成T_Blogs表。 在生成T_Authors表的同时,会生成一张名为_migrationhistory表,这张表用于记录我们对于数据库的更新日志。

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文件,文件内容如下:

 1 public partial class AddEmail : DbMigration
 2 {
 3     public override void Up()
 4     {
 5         //注意,这里数据表的名称是dbo.T_Blogs和dbo.T_Authors而不是我们指定的
 6         //T_Blogs和T_Authors,我们可以把数据表名称改为T_Blogs和T_Authors
 7         //数据表以dbo开头貌似是SQL SERVER中的命名方式,这里小编使用的是MYSQL
 8         CreateTable(
 9             "dbo.T_Blogs",
10             c => new
11                 {
12                     Id = c.Int(nullable: false, identity: true),
13                     Author_Id = c.Int(),
14                 })
15             .PrimaryKey(t => t.Id)
16             .ForeignKey("dbo.T_Authors", t => t.Author_Id)
17             .Index(t => t.Author_Id);
18
19         AddColumn("dbo.T_Authors", "Email", c => c.String(unicode: false));
20     }
21
22     public override void Down()
23     {
24         DropForeignKey("dbo.T_Blogs", "Author_Id", "dbo.T_Authors");
25         DropIndex("dbo.T_Blogs", new[] { "Author_Id" });
26         DropColumn("dbo.T_Authors", "Email");
27         DropTable("dbo.T_Blogs");
28     }
29 }
30     

我们可以看到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:18));
    }

    public override void Down()
    {
        DropColumn("T_Authors", "Age");
    }
}

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

2.2.2  自动迁移

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

参考文章:

自动化 Code First 迁移

What is Code-First

Code First 迁移

时间: 2024-10-12 21:02:40

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

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

前言 写这篇文章的原因,其实由于我写EF core 实现多租户的时候,遇到的问题. 具体文章的链接: Asp.net core下利用EF core实现从数据实现多租户(1) Asp.net core下利用EF core实现从数据实现多租户(2) : 按表分离   (主要关联文章) 这里我遇到的最主要问题是:由于多租户的表使用的是同一个数据库.由于这个原因,无法通过 Database.EnsureCreated() 自动创建多个结构相同但名字不同的表. 所以我在文中提到,需要自己跑脚本去创建多有的

使用CodeFirst创建数据库

CodeFirst的意思是根据EF实体类创建对应的数据结构,创建过程由DotNet框架自己完成,程序员可以部分干涉. 1.CodeFirst数据库策略 CreateDatabaseIfNotExists:默认的策略:如果数据库不存在,那么就创建数据库.但是如果数据库存在了,而且实体发生了变化,就会出现异常. DropCreateDatabaseIfModelChanges:此策略表明:如果模型变化了,数据库就会被重新创建,原来的数据库被删除掉了. DropCreateDatabaseAlways

以编程的方式使用SQLite数据库 执行CRUD(创建 读取 更新 删除)操作

DBAdapter数据库辅助类 package com.databses; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.s

EF框架之CodeFirst创建数据库

CodeFirst是Entity Framework4.1后新增的一种生成模式,在这种方式下,你不需要在DBMS中创建数据库,也无需在VS中画实体模型了,你要做的仅仅是写写代码即可由ORM框架自动创建模型和数据库,非常的方便和简单(由于开发人员只是编写代码,不关心数据库的具体结构,因此也有人把这种方式叫做CodeOnly的). 下面就以一个简单的例子演示一下如何使用CodeFirst生成数据库. 一.新建一个项目并添加必要的引用. 二.编写代码. 1在项目中添加两个实体类和一个数据上下文类如下图

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

System.InvalidOperationException: 支持"XXX"上下文的模型已在数据库创建后发生更改.请考虑使用 Code First 迁移更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269). EF发布时遇到的问题(数据库初始化 http://www.cr173.com/html/17941_1.html) public ZujuanWebSiteDataEntities() : base("cloud_

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

在用VS进行MVC开发的过程中遇到如下问题: 支持“***Context”上下文的模型已在数据库创建后发生更改.请考虑使用 Code First 迁移更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269). 解决了,把数据库中检测模型变化的表(如上图所示)删除就可以了

C# 之 EF CodeFirst创建MySQL数据库

MySQL安装好了,今天跟大家交流一下怎么利用EntityFramework的CodeFirst在MySQL数据库中创建数据库 目标框架:.NET Framework 4 第一步:新建一个项目,然后添加如下的引用,这些引用可以在NuGet中添加,也可以到官网中下载然后添加 第二步:在配置文件中添加数据库节点配置 <span style="font-family:Arial;font-size:10px;"><?xml version="1.0"?&

&quot;支持“xxx”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库”解决办法

学习Asp.Net MVC4 时,使用EF.本来正常,但是由于修改了一下Model中的一个实体类. 导致这个错误. “支持“xxx”上下文的模型已在数据库创建后发生更改.请考虑使用 Code First 迁移更新数据库”. 为了解决上述错误,在Global.asax文件中在 Application_Start后添加以下语句: Database.SetInitializer(new DropCreateDatabaseIfModelChanges<SalesERPDAL>()); 注意需引入命名

EF CodeFirst 更新数据库时报错

今天在博客中看到有网友在更新数据库执行Update-Database时出现下面的错误: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. (provider: SQL Network Interfaces, error: 26 - 定位指定的服务器/实例时出错) . 解决办法,强制更新数据库: Update-Database -ConnectionStringName "My