zoukankan      html  css  js  c++  java
  • Entity Framework Core 2.1,添加种子数据

    EFCore 2.1出来有一段时间了,里面的新功能还没怎么用,今天研究下如何使用EF Core 2.1添加种子数据。

    这部分的官方文档地址是:https://docs.microsoft.com/en-us/ef/core/modeling/data-seeding

    我们在开发时总是需要添加一些种子数据的,所以这个功能还是比较有用的。

    准备工作

    我建立了一个ASP.NET Core项目,里面有几个Model,其中一个是省份Province,另一个是城市City:

    里面还涉及到其它的Model,不过本文用不到,就不贴了。

    该项目使用的数据库是MSSQL LocalDB。并已经做好了上述Models的迁移工作。

    该数据库里面存在过一些数据,但是现在都被我删除了。

    添加第一个种子数据

    直接在DBContext的OnModelCreating方法里使用HasData()方法:

    这里我添加了一个省份的种子数据,并写上了主键Id的值

    数据库该表的主键Id是int自增的。Id为1的数据曾经存在过,但是被我删除了。

    然后看看会发生什么

    生成的迁移类

    命令:Add-Migration Xxx

    看一下生成的迁移类的内容:

    生成的SQL脚本

    命令:Script-Migration

    这是里面关于插入数据的部分:

     迁移到数据库

    命令:Update-Database -Verbose

    结果是成功的。

    看红线那两句话,EFCore在执行的过程中临时更改了设置,可以插入主键的值,然后又禁用了插入主键。

    数据库里面的数据

    虽然曾经存在过Id为1的数据(然后被删除了),但是Id为1的种子数据仍然可以插入进去。

    种子数据的主键必须有值

    我再添加一个没有主键Id值的种子数据:

    然后Add-Migration,看看会发生什么:

    报错了,所以主键值是必填的。

    当我填写了主键值之后,一切都是好用的了:

    更改现有的种子数据

    我在HasData方法里更改了现有的种子数据,但是主键的值并没有改:

    执行Update-Database时的SQL语句:

    可以看到是根据主键对数据库里面的数据进行Update动作。

    其结果也和我想的一样,就是更新了现有的数据:

    如果我把HasData里种子数据的主键值修改了

    我把四川的主键从2改为3。

    看下生成的迁移文件:

    先删除了之前添加的Id为2的种子数据,然后把插入了一笔Id为3的数据。

    看下SQL:

    也是先Delete,再Insert。

    数据库里:

    种子数据为什么要指定主键的值?

     因为在团队开发时,这样可以确保不同的开发人员、电脑、服务器上,在同一个迁移版本具有相同的种子数据

    添加关联种子数据

    Province和City是一对多的关系,也就是说一个Province可以有多个City,而且它们之间有导航属性。

    下面看看一次性添加Province和City是否可以行,我直接在HasData方法里这样写:

    然后Add-Migration

    这样做不行。我必须单独添加City的种子数据,并且设置好外键

    所以正确的做法是:

    这次Add-Migration没有报错,迁移也成功了,看一下最后的数据:

    OK

    如果无法在Model里设置主键/外键

    有时,我们在主从关系的Model里不明确定义外键;有时候我们Model的主键是private set的;

    这时我们就无法在HasData里设置主键/外键的值了,那么如何来添加种子数据呢?

    答案就是使用匿名类

    我把City Model里的外键去掉(导航属性仍然保留,和Province的主从关系依然存在):

    然后就可以这样添加种子数据:

    迁移后的数据:

    结果仍然如预期一样。

    如果主键是Guid类型呢?

    看下数据:

    貌似没问题。

    如果我不修改这个种子数据,再执行一次迁移呢?

    看一下这时的迁移文件:

    删除原来的数据,再插入一个新的数据。。

    数据库里也是这样的:

    所以最好的办法是把Guid的值放在一个变量里

    然后再操作一遍:

    这样就不会出现“把原有数据删掉,再重新插入”这种操作了。

    其它

    使用context.Database.EnsureCreated()会创建一个新的数据库,并包含有种子数据。但是如果数据库已经存在了,那么EnsureCreated()不会更新数据库,也不会添加种子数据了。

  • 相关阅读:
    C#中的String与string
    类和结构的异同点?
    HTTP 无状态啊无状态啊
    重载运算符
    Lambda与委托
    Js与正则表达式
    字符函数PATINDEX()与STUFF()
    C#中的托管与非托管
    原码,反码,补码
    日期函数与转型
  • 原文地址:https://www.cnblogs.com/cgzl/p/9868501.html
Copyright © 2011-2022 走看看