我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Entity Framework Core种子数据Data-Seeding

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Entity Framework Core种子数据Data-Seeding

一、什么是Data-Seeding

Data-Seeding是EntityFrameworkCore 2.1以上版本新增加的特性。在项目刚开始的时候,我们往往是需要初始化一些基础数据到数据库中,通过Data-Seeding特性就可以实现这一功能。本篇文章我们将讲解如何进行数据初始化。

二、初始化方法

具体的数据初始化方法分为如下三种:

  • 模型中配置。这种是通过调用HasData()方法。
  • 手动迁移时添加。
  • 自定义初始化逻辑。

下面我们分别来讲解如何使用这三种方式进行数据迁移。

1、模型中配置

这种方式是通过调用HasData()方法实现的。这种也是我在项目开发过程中,经常使用的。这种方式是在数据上下文类中重写OnModelCreating()方法,我们先看HasData()方法的定义:

可以看到,方法的参数可以是Blog类型的数组,具体代码如下:

using EFCore.Model;
using Microsoft.EntityFrameworkCore;

namespace EFCore.Data
{
    /// <summary>
    /// 数据上下文
    /// </summary>
    public class EFDbContext:DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Data Source=.;Initial Catalog=EFTest;User ID=sa;Password=123456;");
        }

        public DbSet<Blog> Blogs { get; set; }


        /// <summary>
        /// 重写OnModelCreating方法
        /// </summary>
        /// <param name="modelBuilder"></param>
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // 针对Blog实体添加种子数据
            modelBuilder.Entity<Blog>().HasData(
                new Blog()
                {
                    // Id字段要赋值,否则会报错
                    Id=1,
                    Name="ef core"
                },
                new Blog()
                {
                    Id=2,
                    Name="ASP.NET Core"
                },
                new Blog()
                {
                    Id=3,
                    Name="图解数据结构"
                }
                );
            base.OnModelCreating(modelBuilder);
        }
    }
}

我们注意到:默认情况下会自动设置Id列为主键,并且是自动增长的。但是这里要设置Id的值,即使Id是自动生成的主键,否则会报下图所示的错误:

添加完种子数据以后,我们运行程序,查看输出结果:

查看数据库:

这样就生成了数据库和表,而且表里面也有了初始化数据。

假如这时候我们想增加一条数据,代码如下:

using EFCore.Model;
using Microsoft.EntityFrameworkCore;

namespace EFCore.Data
{
    /// <summary>
    /// 数据上下文
    /// </summary>
    public class EFDbContext:DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Data Source=.;Initial Catalog=EFTest;User ID=sa;Password=123456;");
        }

        public DbSet<Blog> Blogs { get; set; }


        /// <summary>
        /// 重写OnModelCreating方法
        /// </summary>
        /// <param name="modelBuilder"></param>
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // 针对Blog实体添加种子数据
            modelBuilder.Entity<Blog>().HasData(
                new Blog()
                {
                    // Id字段要赋值,否则会报错
                    Id=1,
                    Name="ef core"
                },
                new Blog()
                {
                    Id=2,
                    Name="ASP.NET Core"
                },
                new Blog()
                {
                    Id=3,
                    Name="图解数据结构"
                },
                // 新增加一条数据
                new Blog()
                {
                    Id=4,
                    Name="C#高级编程"
                }
                
                );
            base.OnModelCreating(modelBuilder);
        }
    }
}

这时候还能不能用刚才的方法呢?我们这时在运行程序,查看结果:

这时候程序执行失败了,而且表里面的数据也没有增加。这说明context.Database.EnsureCreated()方法只有在第一次执行的时候才会有效,以后数据进行更改后就无效了。那么有什么方式可以实现呢?这时只有通过命令行进行迁移或者通过context.Database.Migrate方法调用生成的迁移类才能对数据的更改有效。

我们把刚才生成的数据库删掉,新增加的那条数据注释掉,然后使用命令行迁移的方式生成数据库表,首先添加迁移:

然后更新数据库:

更新完数据库以后,我们在HasData()方法里面添加一条数据,然后再次执行上面的添加迁移和更新数据库的命令,发现这时候数据库里面会添加新增加的数据。

在执行完第二次添加迁移命令后,如果不使用更新数据库命令,也可以通过代码的方式进行迁移,这就是调用context.Database.Migrate命令,代码如下:

using EFCore.Data;
using Microsoft.EntityFrameworkCore;
using System;

namespace EFCore.Con
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            EFDbContext dbContext = new EFDbContext();
            // 迁移
            dbContext.Database.Migrate();
            //bool tfTrue = dbContext.Database.EnsureCreated();
            //if(tfTrue)
            //{
            //    Console.WriteLine("数据库创建成功!");
            //}
            //else
            //{
            //    Console.WriteLine("数据库创建失败!");
            //}

            Console.ReadKey();
        }
    }
}

这时会自动调用最新的迁移文件去更新数据库。

注意:调用该方法对数据的更改只有在迁移时才能生效,也就是说只有通过命令进行迁移或者通过context.Database.Migrate方法调用生成的迁移类才能对数据更改有效。而调用context.Database.EnsureCreated()方法只有在第一次执行的时候才有效,但数据进行更改后将无效。

这种方式有两种限制:

  • 必须指定主键的值(即使主键由数据库自动生成也要指定值)。
  • 添加的必须是静态数据,没有任何的依赖。比如添加的Id主键的值在其它表里面有引用就不可以。

2、手动迁移时添加

这种方式在这里不进行讲解,有兴趣的可以参考微软的官方文档。

3、自定义初始化逻辑

执行数据种子设定的一种简单而有效的方法是在主应用程序逻辑开始执行之前使用使用DbContext.SaveChanges()。代码如下:

using EFCore.Data;
using EFCore.Model;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;

namespace EFCore.Con
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            //EFDbContext dbContext = new EFDbContext();
            //// 迁移
            //dbContext.Database.Migrate();
            ////bool tfTrue = dbContext.Database.EnsureCreated();
            ////if(tfTrue)
            ////{
            ////    Console.WriteLine("数据库创建成功!");
            ////}
            ////else
            ////{
            ////    Console.WriteLine("数据库创建失败!");
            ////}

            #region 使用自定义初始化逻辑
            using(EFDbContext context=new EFDbContext())
            {
                context.Database.EnsureCreated();

                var testBlog = context.Blogs.FirstOrDefault(p => p.Name == "C#");
                if(testBlog == null)
                {
                    // 添加数据
                    context.Blogs.Add(new Blog()
                    {
                        Name = "C#"
                    });
                }

                // 保存数据
                context.SaveChanges();
            }
            #endregion
            Console.ReadKey();
        }
    }
}

通过这种自定义逻辑的方式也可以添加种子数据。如果HasData()方法里面添加了种子数据,那么会先把HasData()方法里面的种子数据添加到数据库中。如果没有名称为C#的数据,则还会在添加一条数据。

如果有了该数据,就不会再添加了。

注意:这种方式新增数据的时候就不能再给主键Id赋值了,因为是先生成数据库,自动设置Id为主键,在添加数据的时候会自动赋值。

三、Data-Seeding本质

  • 当调用HasData()方法首次迁移时,实质上是调用MigrationBuilder类中InsertData方法进行插入。
  • 当调用HasData()方法更改数据(未更改主键)时,实质上是调用MigrationBuilder类中UpdateData方法进行更新操作。
  • 当调用HasData()方法移除数据或更改主键时,实质上是调用MigrationBuilder类中DeleteData方法进行删除操作或者删除和更新操作。

1、首次迁移

我们在第一次执行完添加迁移命令以后,会生成一个迁移文件,如下图所示:

可以看到这时就是调用的InsertData方法来新增数据。

2、修改不是主键的数据

我们修改数据,将ef core修改为ef core 3.1.1,如下图所示:

修改完以后我们在执行迁移命令,如图所示:

这时在去看生成的迁移文件:

这时执行的就是UpdateData方法。

3、删除数据

接着我们把Id为1的数据在代码里面注释掉模拟删除操作,在执行迁移命令:

在看生成的迁移文件:

可以看到这次就是执行的DeleteData方法。

4、修改主键数据

我们在把Id为2的数据修改为6:

在执行迁移:

查看生成的迁移文件:

这次就是先执行DeleteData方法,然后在执行InsertData方法。

四、总结

针对种子数据初始化,主要有上面的三种方式,比较推荐的是第一种和第三种,可以根据自己的使用情况来选择适合自己的。

到此这篇关于Entity Framework Core种子数据Data-Seeding的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Entity Framework Core种子数据Data-Seeding

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Entity Framework Core种子数据Data-Seeding怎么配置

这篇文章主要介绍“Entity Framework Core种子数据Data-Seeding怎么配置”,在日常操作中,相信很多人在Entity Framework Core种子数据Data-Seeding怎么配置问题上存在疑惑,小编查阅了各
2023-06-29

如何使用Entity Framework Core对Web项目生成数据库表

小编给大家分享一下如何使用Entity Framework Core对Web项目生成数据库表,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、引言这篇文章中我们讲解如何在Web项目中使用EntityFrameworkCor
2023-06-29

Entity Framework Core如何使用控制台程序生成数据库表

这篇文章主要介绍了Entity Framework Core如何使用控制台程序生成数据库表,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、引言我们使用Code First的
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录