应无所住,而生其心
排名
1
文章
860
粉丝
112
评论
163
net core webapi post传递参数
庸人 : 确实坑哈,我也是下班好了好几次,发现后台传递对象是可以的,但...
百度编辑器自定义模板
庸人 : 我建议换个编辑器,因为现在百度富文本已经停止维护了,用tinymec...
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

.NET CORE EF数据库迁移,以及迁移命令详解。code first。在不删除表的情况下保持同步

9437人阅读 2019/12/22 9:52 总访问:5182824 评论:0 收藏:0 手机
分类: EF

.NET CORE EF 数据库迁移需要的依赖

  1. Install-Package Microsoft.EntityFrameworkCore.SqlServer -version 3.1.1
  2. Install-Package Microsoft.EntityFrameworkCore.Tools -version 3.1.1
  3. Install-Package Microsoft.EntityFrameworkCore.Design -version 3.1.1

或者使用ItemGroup的方式安装依赖

  1. <ItemGroup>
  2. <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.1">
  3. <PrivateAssets>all</PrivateAssets>
  4. <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  5. </PackageReference>
  6. <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.1" />
  7. <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.1">
  8. <PrivateAssets>all</PrivateAssets>
  9. <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  10. </PackageReference>
  11. </ItemGroup>

也不一定全部都要用到,根据实际情况来。Tools 库里边其实就包含了Design库

以前的迁移命令

Enable-Migrations –EnableAutomaticMigrations

已经过时不能使用了

新的命令

Add-Migration InitialCreate

一般第一次执行的初始化迁移,都是创建表,这些。还会生成数据库快照文件XXModelSnapshot.cs。

更新到数据库的命令

Update-Database [迁移名称]
后边的迁移名称是可选的,可以接迁移名称,例如: Update-Database AddColumn

上面都是比较简单的描述了一下,留下两个问题

1:怎么可以跳过某个迁移步骤,比如数据库已经存在的情况下,初次执行迁移命令会生成对数据库的创建,如果不跳过,会出现xx表已经存在的错误

2:Update-Database [迁移名称]接或者不接有什么不同


迁移命令详解

Add-Migration 迁移名称

执行一次迁移,创建迭代版本,相当于做一个记录,生成迁移代码。

如果该命令是首次创建,则会在执行命令的项目下生成Migrations文件夹,
创建数据库快照文件XXModelSnapshot.cs,以及本次迭代文件。如图


添加迁移时,EF会通过将数据模型与快照文件进行对比来确定已更改的内容。
使用get-help Add-Migration -detailed,可以查看到Add-Migration的使用详情。

如果是第一次执行迁移命令会生成对表的创建和删除,UP方法就是对表的创建,Down方法就是对表的删除

所以如果数据库中有表在执行Update-Databas命令的话会报错,提示表已经存在

所以如果你数据库已经在前面创建好了,可以把初次执行迁移命令生成的版本删除掉。不然就算你执行Update-Database的时候接一个迁移名称,还是会报错,因为初始化那一步你没有执行成功,就算你接迁移名称还是会去执行没有执行过成功的迁移文件,所以还是会报错,目前还没有找到一个命令可以只执行一个指定的迁移名称。估计他要这样设计也是为了让迁移记录和数据库保持一致性。

其实要解决重复创建表的问题,也不一定要删除首次创建的迁移文件,干掉迁移文件里边的Up和Down内容也是可以的,这样执行Update-Database就不会有问题了,因为不会重新在去创建一次表。(但是最好不要手动删除迁移文件,因为快照文件里边还有记录,直接手动删除可能也会造成迁移记录的错乱,所以要撤销迁移,或者删除迁移最好使用命令Remove-Migration来)

当然还有一种方法,就是向添加迁移日志表中添加想要跳过的记录,因为ef判断某一个迁移是否执行,是根据迁移表EFMigrationsHistory来的。比如你想跳过20211217011025_InitialCreate这一步,向迁移表中添加这条记录就行,

所以在执行更新数据库的时候想要跳过某步,这里说了三种方法。
1:删除对应的迁移文件
2:删除或者注释掉迁移文件里边的内容,本质和第一步其实是一样的
3:向迁移表__EFMigrationsHistory中添加需要跳过的迁移步骤

add-migration —context XXXDbContext
一个程序集下面存在多个DbContext 指定DbContext进行迁移


Update-Database [迁移名称]

更新到数据库。该命令更新所有未执行的迭代版本。调用的是迭代文件中的Up方法
Update-Database [迁移名称],后边也可以接迭代名称,就针对性执行某个迁移了
接名称完整的写法:Update-Database -Migration 迁移名称

执行成功可以在数据库看到执行的日志

输入get-help Update-Database -detailed,可以查看到Update-Database的使用详情。

上面说过,就算你接一个迁移名称,并不是只执行那一个迁移版本,前面如果有执行失败的,就算你接了一个迁移名字,还是会执行那个失败的版本。

那么问题就来了,既然接不接迁移名称都会执行前面没有执行过的或者执行失败的,那么接名称的意义在哪里呢?都是根据迁移日志来决定执不执行。
其实是这样的在你执行迁移命令接名称的时候,在这个迁移文件,以及迁移文件之前的都要成功执行,相当于这个名称是指定一个目标点,到这个点截至,如果不接迁移名称就是所有的迁移文件执不执行都是根据日志来的,而迁移日志又是执行成功才会添加的,所以就是说必须要保证到这个迁移文件为止的全部要成功才行。
所以如果你指定的迁移名称是最后一个没有执行的版本,那么接不接都一样,因为执行的截至点都是那一个,只有当有多个迁移文件没有执行的时候接不接迁移名称才有区别。
他并不会跳过中间没有执行的,或者执行失败的,而是到这个名称为止的所有迁移文件都要保证执行成功。

比如我们执行Update-Database -Migration AddColumn_LL,它会执行到这个文件为止,也就是检查前三个文件有没有被成功执行,没有成功执行或者没有执行过的都会执行。但是他并不是执行AddColumn_PP这个文件,也就是说它后面的不会管。
如果执行的是Update-Database -Migration AddColumn_PP,就会检查这里的所有迁移文件了,由于这里是时间点最后的一个迁移文件,所以接不接这个名称都一样。

接名称还有一个意义就是回归到某个版本,当然要回归到某个版本,前提是这个版本成功应 用过。比如上图的例子,假如所有版本都成功执行了,我想要回归到AddColumn这个版本就可以执行,Update-Database -Migration AddColumn,想要回归到AddColumn_LL版本,就执行Update-Database -Migration AddColumn_LL即可。这个回归版本的意思就是让数据库保持到这一步执行后的效果。所以你执行的是最后一步的话Update-Database -Migration AddColumn_PP,相当于就是最新的迁移版本了,并不是说回退到AddColumn_PP版本没有执行之前的版本,而是回到这个版本执行成功的版本。


Remove-Migration 回滚命令,回滚最后一次的操作,撤销本次更新的内容

撤销本次更新的内容,调用的是Down方法中的内容
回滚最后一次的操作,也就是当前的操作。官方解释:Removes the last migration.

查看命令详情

  1. get-help Remove-Migration -detailed

执行的效果:

它会把这次迁移的迁移文件删除掉,而且会把快照的修改也还原。所以如果执行了迁移又想还原这次迁移就可以使用这个撤销命令。这次测试的是迁移还没有更新到数据库的情况。

如果执行Remove-Migration 报错:has already been applied to the database

他说已经成功更新到了数据库,给你做一个提示。如果你要确定更新,可以使用如下命令即可。

  1. Remove-Migration -Force

Remove-Migration -Force:回滚最近的一次迁移记录
会把本次生成的迁移文件删除掉,还有后缀为ModelSnapshot的快照文件也撤销,因为这里边也会记录操作内容。所以如果这次迁移执行部分成功,部分失败的话,执行这个命令不会让更新数据库的还原,只会删除迁移文件,所以数据库的操作你可能需要手动去数据库处理一下(比如附表存在的情况下添加外键,因为数据问题造成了表添加成功了,外键没有添加成功的情况,自己在数据库处理一下就行也很加拿大)。

当然你可以先执行Update-Database -Migration:0 ,删除表结构
然后再执行:Remove-Migration (删除迁移文件)。当然如果迁移已经应用到了数据库这个命令要特别慎用,他好像某些情况下会把你前面执行的表都删除掉。所以完全不建议这样使用。

迁移记录,迁移文件和数据库不一致的情况下。如果在不删除表的情况下保持同步。(可以参考下面的快照文件同步法,可能还要简单一点)


正常情况下code first都是通过代码生成数据库,迁移文件,迁移记录,快照文件都应该和数据库一致,但是有些情况下,是先写了数据库,然后在写的代码,这样就会造成,迁移记录和数据库不一致了。这种情况下,如果后面又增加了表,或者更改了字段等等,在去执行数据库迁移的时候就会出现问题。(比如团队中有些人不会使用迁移命令乱整-.-)

比如数据库收手动加了一个role表,不是通过迁移文件去创建的,这个时候执行数据库更新就会提示,role表已经存在了,因为他没有在迁移文件中记录到。

解决方法:

先让role表的创建保持迁移文件和数据库一致后,在去做其他修改。但是如何保持一致呢,role表明明就不是迁移文件生成的数据库,而是手动在数据库中创建的表。其实很简单,我们上面知道原理后就可以解决这种问题了,不用在去把数据库干掉在重新执行迁移命令了。

先把后面相关修改的注释掉,比如在role表同步只会想要的操作,都注释掉,就是要让当然实体的内容和数据库的表保持一致。然后把快照文件删除掉,执行一次迁移Add-Migration -fb(名字随便取,这里我写的tb就是同步的简拼),然后这个时候我们就不去执行Update-Database更新数据库了,如果执行还是会报错的,因为数据库表已经存在了,我们的目的就是让迁移文件和数据库保持一致,所以我们要让ef认为我们这个命令是成功执行了的,我们只需要在数据库迁移记录表中手动添加一条记录即可。

然后就ok了,后面正常使用即可。


为什么要删除快照呢?如果不删除快照的话,执行后面的迁移估计没有任何内容的,因为创表这些操作已经记录在快照文件里边的。这就是为什么要做撤销操作,不能手动删除迁移文件,如果快照里边还有操作记录哇,你手动删除迁移文件,如果在执行一次Add-Migration它会什么都没有改变的。所以要像撤销操作要使用Remove-Migration命令或者Remove-Migration -Force。

-。-录了一个讲解的视频,后面才发现没有声音

数据库迁移解决方法之-快照文件同步法

比如添加了迁移记录然后更新到数据库的时候报错:重复创建字段,PreviewUrl。

问题分析。
不知道什么原因造成快照和数据库不一致,数据库里边文件管理表有PreviewUrl字段,但是快照里边没有PreviewUrl字段,所以执行迁移的时候就会这个字段已经有了导致迁移失败,所以在快照里边增加去添加一下这个字段,就好了

数据库和代码就同步了。在执行后面的操作就不会有问题了。
知道原理了,啷个方便啷个操作就行了,一句话。在进行迁移操作数据库的时候,要保证快照文件和数据库对应。
其实正常操作的话他肯定都是对应的哇,各种骚操作导致没有对应上也没有关系,[狗头]手动改一下就完事,怕的是不懂这个原理,改不了就麻烦了。知道原理了随便操作,不慌。

真正生成迁移记录里边的操作是根据快照和数据比较的,有什么改变就生成对应的操作。所以如果快照文件内容和数据库不一致的时候,在去生成一个数据库库迁移操作就会问题,比如上面提到的重复创建字段PreviewUrl的问题。

简单的总结,快照文件介绍

ef的数据库迁移,主要就是几个命令的使用,但是想要用好,需要对里边的原理比较了解。其实原理核心点就是迁移记录,迁移快照,迁移表,把这些搞清楚了,就可以很灵活的使用ef的数据库迁移了。

上面对迁移,和迁移记录表介绍得比较多。数据库快照得话,其实就是当前的一个数据的创建记录,要和数据库保持同步,才能更好的去修改数据库。

比如像快照的这样一段
记录了表的导航属性,外键等信息,当然这个文件其他地方也有这个表的字段这些信息记录。

执行迁移文件的时候就是根据这个快照文件和你的代码进行比较,才知道你进行了哪些修改,然后在生成对应的操作数据库的语句的迁移记录文件,执行update-databases的时候在根据迁移文件和数据库的迁移记录比较,在去操作数据库,整体的一个原理和执行流程大概就是这样。想要更好的理解这些原理,可以自己创建一个简单的项目,然后去修改实体,看看迁移文件,迁移记录表,快照的变化即可。

执行迁移命令的时候,除了快照和实体类对比,还会受到数据库版本,创建数据库的设置影响,比如开始连接点win下面的mysql数据库换到linux下的docker的MySQL,有些类型会不同,ef也会检查到,比如以前连接的是在win下面的mysql时间类型是datetime类型,换到了linux下的docker的MySQL时间类型执行迁移的时候就会全部变成了datetime(6)了


欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)

评价

.net core EF json序列化循环引用问题

直接贴代码:services.AddControllersWithViews() .AddNewtonsoftJson(options=&gt; { options.SerializerSettings.Cont...

.net core EF处理并发冲突

当某用户显示实体数据以对其进行编辑,而另一用户在上一用户的更改写入数据库之前更新同一实体的数据时,会发生并发冲突。 ...

.net core EF Fluent API配置外键

和以前的写法变了一点点,以前HasRequired换成HasOne即可。以前的写法://1:先配置多的一方(按照多对一方式来配置) model...

abp数据库迁移

让我们来了解数据库迁移吧!还坑了我好久哇!一、首先二、出现程序包后按以下步骤做如果没按照以上步骤做的话你输入的是add...

core ef中执行数据库迁移无效

是因为差一个依赖项Microsoft.EntityFrameworkCore.Tools下载即可:nuget命令:Install-PackageMicrosoft.EntityFrameworkC...

ef数据库迁移命令的依赖项

ef数据库迁移的依赖项是: Microsoft.EntityFrameworkCore.Tools下载即可:nuget命令:Install-PackageMicrosoft.EntityFra...

ef数据库迁移命令

.net core 数据库迁移可以参考:https://www.tnblog.net/aojiancc2/article/details/5370可以使用get-help命令查看命令的详...

EF数据库迁移

点击工具(打开库程序包管理器,再打开库程序包管理器控制台)迁移数据库的命令Enable-Migrations启用数据库迁移Enable-Mig...

CodeFirsrt数据库迁移

数据库迁移我们如果已经使用了使用CodeFirst创建数据库,但是突然又想增加或者删除一个字段的时候,如果直接去数据库里把数...

css弹性盒子flex布局

css弹性盒子由于版本不同浏览器问题造成了一些不同的写法display:flexbox;在google浏览器中如果使用下面的写法就不行displa...

可输入下拉文本框据输入动态加载数据 jquery-editable-select

用到一个jquery-editable-select的控件github地址:https://github.com/indrimuska/jquery-editable-select这个插件的原理是...

.net mvc分部页.net core分部页

.net分部页的三种方式第一种:@Html.Partial(&quot;_分部页&quot;)第二种:@{ Html.RenderPartial(&quot;分部页&quot;);}...

css中单位pxemrem和vh/vw的理解

&gt;px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。em是相对长度单位。相对于当前对象内文本的字...

让IIS支持webp格式图片让IIS支持vtt格式iis设置mime类型iis配置支持的类型

webp格式图片可以让图片体积变小。也让下载图片变得更加困难一点 在线制作webp工具 https://www.upyun.com/webp?utm_mediu...

网页上传文件断点续传的实现无视文件大小上传以及datatables基本用法

首先明白js是客户带执行代码,c#是服务器上执行代码。本地文件需要用到js处理,服务器端接受c#代码处理1.HTML页面,文件信...