• Entity Framework Core 之数据库迁移


    前言

    最近打算用.NET Core写一份开源的简易CMS系统,来练练手

    所以又去深入研究了一下Entity Framework Core 

    发现其实有些细节园子里还是很少讲到.

    特意整理了几个细节.

    正文

    1.数据库迁移

    先了解一下什么是"数据库迁移",它提供了一种方法,可以逐步将Code First的实体架构更改应用于数据库,以保持数据库与EF Core模型同步,同时保留数据库中的现有数据。

    EF Core的数据迁移相对EF6来说改了不少也简化了一些.所以我们现在就来看看如何进行数据迁移

    我们以官方代码来做为例子..先来创建一个简单的上下文.

        public class BloggingContext : DbContext
        {
            public BloggingContext()
                : base()
    
            {
            }
            private static ILoggerFactory Mlogger => new LoggerFactory();
                   
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                Mlogger.AddProvider(new MyFilteredLoggerProvider());
                var loggerFactory = 
                     optionsBuilder
                    .UseMySql(@"链接地址");
               
            }
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
            }
    
            public DbSet<Blog> Blogs { get; set; }
            public DbSet<Post> Posts { get; set; }
        }
    
        public class Blog
        {
            public int BlogId { get; set; }
            public string Url { get; set; }
    
            public List<Post> Posts { get; set; }
        }
    
        public class Post
        {
            public int PostId { get; set; }
            [MaxLength(50)]
            public string Title { get; set; }
            public string Content { get; set; }
    
            public int? BlogId { get; set; }
            public Blog Blog { get; set; }
        }
    }

    然后我们通过Nuget来添加引用.

    Microsoft.EntityFrameworkCore.Tools

    打开NuGet包管理控制台

    选择默认项目为实体上下文所在的程序集如下:

    首先我们需要添加一个迁移版本.

    执行命令如下:

    Add-Migration BanBen1(这里是版本的名称,可以自己定义)

    我们会发现Model程序集下多了一个文件夹为Migrations里面有3个文件.如下:

    • XXXXXXXXXXXXX_BanBen1.cs - 主迁移文件。包含应用迁移(in Up())和恢复(in Down()所需的操作。
    • XXXXXXXXXXXXX_BanBen1.Designer.cs - 迁移元数据文件。包含EF使用的信息。
    • BloggingContextModelSnapshot.cs - 当前模型的快照。主要用于确定添加下一次迁移时发生了哪些变化.

    然后我们执行命令

    Update-Database

    如果你的数据库没创建,是第一次,就会执行成功,

    如果你前期创建过数据库.但是是第一次创建迁移..就会失败.(注意这里!!)

    因为第一次生成的迁移方法是按照新增来迁移的..而不是修改.

    错误信息可能会如图:

    解决方法是找到XXXXXXXXXXXXX_BanBen1.cs - 主迁移文件,删除Up和Down里面的代码.

    删除后如下:

        public partial class BanBen1 : Migration
        {
            protected override void Up(MigrationBuilder migrationBuilder)
            {
    
            }
    
            protected override void Down(MigrationBuilder migrationBuilder)
            {
              
            }
        }

    其实这次迁移就没有修改数据库任何信息..

    我们在来创建第二个迁移版本..

    首先,我们修改实体类..给Post的Content加上长度限制,如下:

     public class Post
        {
            public int PostId { get; set; }
            [MaxLength(50)]
            public string Title { get; set; }
            [MaxLength(50)]
            public string Content { get; set; }
    
            public int? BlogId { get; set; }
            public Blog Blog { get; set; }
        }

    然后我们开始迁移..

    记得每次迁移,都需要创建一个迁移版本!

    我们执行命令如下(注意,我们的版本已经改为了2):

     Add-Migration BanBen2

    成功创建迁移文件之后,我们更新数据库.

    Update-Database

    成功信息如下:

    然后我们进入数据库看看效果:

    我们发现Content的长度限制已经改为了50

    2.删除迁移

     有的时候我们刚刚创建了一个迁移,还没应用到数据库,就发现自己需要变更实体.那我们就可以删除这个没有应用的迁移版本.

    执行命令如下:(注意,这里是没有应用过的迁移,可以删除.如果应用过了.则会收到错误信息)

    Remove-Migration

    3.迁移回滚.

    有些时候,我们需要回滚到之前的一个迁移版本.,比如我们部署的时候,开发版本和稳定版本肯定不一样..

    那么我们就会用到回滚命令.

    执行如下:

    Update-Database 这里填写需要回滚的版本名

    ,比如我们执行如下:

    Update-Database BanBen1

    然后我们会发现,BanBen2中的长度限制,已经没有了..

    4.生成一个迁移SQL脚本

    有的时候,我们的生产数据库,是需要用脚本来创建库的.所以我们也可以直接通过实体来生成SQL脚本.命令如下:

    Script-Migration

    就会生成对应的迁移SQL脚本.如下:

    CREATE TABLE `__EFMigrationsHistory` (
        `MigrationId` varchar(95) NOT NULL,
        `ProductVersion` varchar(32) NOT NULL,
        CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`)
    );
    
    INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
    VALUES ('20180316015722_BanBen1', '2.0.2-rtm-10011');
    
    ALTER TABLE `Posts` MODIFY COLUMN `Content` varchar(50) NULL;
    ALTER TABLE `Posts` ALTER COLUMN `Content` DROP DEFAULT;
    INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
    VALUES ('20180316022508_BanBen2', '2.0.2-rtm-10011');

    当然,这个脚本可以自定义需要迁移的版本号.文件名,需要生成迁移脚本的上下文(多个上下文的情况).

    5.迁移脚本的帮助说明.

    我们可以通过命令来获取帮助说明

    Get-Help about_EntityFrameworkCore
    get-help Add-Migration -full
    get-help Script-Migration -full

    .

  • 相关阅读:
    【C++ 基础 | vector 01】vector 用法及代码代码示例
    【力扣 101】706. 设计哈希映射
    【C++ 继承 | 智能指针 02】weak_ptr
    【C++ 继承 | 虚函数表 02】C++虚函数表剖析 ②
    【力扣 104】142. 环形链表 II
    【力扣 100】705. 设计哈希集合
    【力扣 099】641. 设计循环双端队列
    【C++ 基础 | 智能指针 01】shared_ptr 详解
    【力扣 103】141. 环形链表
    【力扣 102】695. 岛屿的最大面积
  • 原文地址:https://www.cnblogs.com/GuZhenYin/p/8579420.html
Copyright © 2020-2023  润新知