侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

在.NET Core类库中使用EF Core迁移数据库到SQL Server的方法

数据库  /  管理员 发布于 6年前   307

前言

如果大家刚使用EntityFramework Core作为ORM框架的话,想必都会遇到数据库迁移的一些问题。

起初我是在ASP.NET Core的Web项目中进行的,但后来发现放在此处并不是很合理,一些关于数据库的迁移,比如新增表,字段,修改字段类型等等,不应该和最上层的Web项目所关联,数据的迁移文件放到这里也感觉有点多余,有点乱乱的感觉,所以才想着单独出来由专门的项目进行管理会比较好,也比较清晰!

注意目标框架选择的是.NET Core 2.0而不是.NET Standard 2.0。

0、前期准备

a)、表实体定义,这个是在.NET Standard 2.0的类库中存放的。

/// <summary> /// 系统应用的用户实体 /// </summary> public class ApplicationUser : BaseModel {  /// <summary>  /// 用户名  /// </summary>  public string UserName { get; set; }  /// <summary>  /// 密码  /// </summary>  public string Password { get; set; }  /// <summary>  /// 邮件地址  /// </summary>  public string Email { get; set; } }

b)、新建一个.NET Core 2.0的类库,并定义好我们所要使用的数据库上下文,很简单,接下来开始我们的正文

/// <summary> /// 系统上下文 /// </summary> public class LightContext : DbContext {  public LightContext(DbContextOptions<LightContext> options) : base(options)  {  }  /// <summary>  /// 系统应用用户  /// </summary>  public DbSet<ApplicationUser> ApplicationUser { get; set; }  /// <summary>  /// 角色表  /// </summary>  public DbSet<Role> Role { get; set; } }

1、问题汇总

首先要确保仓储类库中已经引入以下两个Nuget包,没有的话请使用包管理器进行安装。不建议直接引入原包:Microsoft.AspNetCore.All,按需引入即可

Install-Package Microsoft.EntityFrameworkCore.SqlServerInstall-Package Microsoft.EntityFrameworkCore.Tools

a)打开CMD,然后切换到类库所在路径下,执行以下命令。不过你也可以使用程序包管理器控制台(PMC)进行迁移,但是会有少许变化,部分命令见下表:

迁移命令描述 CMD命令 PMC命令
创建迁移:migrationname为迁移名称 dotnet ef migrations add migrationname add-migration migrationname
移除迁移(删除最近的一次迁移) dotnet ef migrations remove remove-migration
应用最新的迁移(使迁移文件应用到数据库) dotnet ef database update update-database
应用指定的迁移 dotnet ef database update migrationname update-database migrationname
查看迁移列表 dotnet ef migrations list
查看数据库上下文信息 dotnet ef dbcontext info

dotnet ef

错误提示:

未找到与命令“dotnet-ef”匹配的可执行文件

解决方法:

在项目文件Light.Repository.csproj中添加以下节点

<ItemGroup> <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.1" /></ItemGroup>

重新执行上面的命令,如果出现了EF Core的标志(一头蓄势待发的野马)表示已经成功

b)、执行以下命令进行迁移

dotnet ef migrations add InitLightDB

错误提示:

The specified framework version '2.0' could not be parsed
The specified framework 'Microsoft.NETCore.App', version '2.0' was not found.
- Check application dependencies and target a framework version installed at:
\
- Alternatively, install the framework version '2.0'.

解决方法:

在项目文件中添加以下节点:

<PropertyGroup> <TargetFramework>netcoreapp2.0</TargetFramework> <RuntimeFrameworkVersion>2.0.3</RuntimeFrameworkVersion> </PropertyGroup>

c)、重新执行b步骤的命令,报错信息如下:

错误提示:

Unable to create an object of type 'LightContext'. Add an implementation of 'IDesignTimeDbContextFactory<LightContext>' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.

这个问题如果是在Web项目,并且配置了DbContext的链接字符串的话,是不会出现此问题的。很显然是迁移命令没有找到DbConnectionString导致的,接下来我们按照提示,实现一个IDesignTimeDbContextFactory<LightContext>试试

解决方法:

创建一个与DbContext同一目录下的DesignTimeDbContextFactory文件,然后实现接口中的方法CreateDbContext,并配置ConnectionString

public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<LightContext> {  public LightContext CreateDbContext(string[] args)  {   var builder = new DbContextOptionsBuilder<LightContext>();   builder.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Integrated Security=true;Initial Catalog=Light;");   return new LightContext(builder.Options);  } }

再次执行迁移命令,终于成功了。

成功提示:

Done. To undo this action, use 'ef migrations remove'

同时类库下面会生成Migrations文件夹以及相关的迁移文件

2、小试迁移命令

a)、使用以下命令应用迁移,生成数据库和表

dotnet ef database update

通过VS的SQL Server资源管理器查看生成数据库的结构,其中__EFMigrationsHistory为每次迁移的记录表

b)、因为string类型的字段迁移到数据库之后的数据类型为nvarchar(max)并且是可空类型的,下面我们就使用Fluent API对ApplicationUser表字段进行配置,同样你也可以使用属性注解的方式进行配置,因为我自己不喜欢“污染”表实体

public static void ConfigApplicationUser(ModelBuilder modelBuilder)  {   modelBuilder.Entity<ApplicationUser>(m =>   {    m.Property(t => t.Email)      .HasMaxLength(50);    m.Property(t => t.UserName)      .IsRequired()      .HasMaxLength(50);    m.Property(t => t.Password)      .IsRequired()      .HasMaxLength(20);   });  }

然后同样使用上面的两条命令重新迁移并更新数据库结构

观察数据库表结构已经更新

同理添加字段,删除字段都是一样的迁移操作,还是很方便的

3、扩展

a)、为了方便演示,其实上面在类库中执行迁移时的数据库连接字符串是写死的,那么最好的办法是应该去读取Web项目下已经配置好的连接,这样就能保证上下的一致性,不用再去为了EF的迁移而单独维护一个多余的数据库连接配置。改造也很简单,即通过Configuration组件读取appsettings.json的ConnectionStrings节点,改造之后是这样子的:

public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<LightContext> {  public LightContext CreateDbContext(string[] args)  {   Directory.SetCurrentDirectory("..");//设置当前路径为当前解决方案的路径   string appSettingBasePath = Directory.GetCurrentDirectory() + "/Light.AuthorityApi";//改成你的appsettings.json所在的项目名称   var configBuilder = new ConfigurationBuilder()    .SetBasePath(appSettingBasePath)    .AddJsonFile("appsettings.json")    .Build();   var builder = new DbContextOptionsBuilder<LightContext>();   //builder.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Integrated Security=true;Initial Catalog=Light;");   builder.UseSqlServer(configBuilder.GetConnectionString("LightConnection"));   return new LightContext(builder.Options);  } }

注意需要额外引入下面这个Nuget包:

Install-Package Microsoft.Extensions.Configuration.Json

b)、属性注解[Column(Order = 1)]对EF Core来说还没有达到可以调整数据库生成字段的顺序,不过我们还是可以修改迁移文件的实体属性的顺序来达到我们想要的效果。下面是我调整之后重新生成的表,是不是看出来和上面的有什么不同,一图胜万语:

c)、最后一步,自己动手试试看:创建一个SeedData迁移文件来添加数据库的初始数据。:)

4、最后

EF Core的强大远不止这些,还有更多的使用方法等着我们去发现,去探索。每天进步一点点,是件很愉快的事情!


  • 上一条:
    .net Core连接MongoDB数据库的步骤详解
    下一条:
    asp.net mvc CodeFirst模式数据库迁移步骤详解
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 分库分表的目的、优缺点及具体实现方式介绍(0个评论)
    • DevDB - 在 VS 代码中直接访问数据库(0个评论)
    • 在ubuntu系统中实现mysql数据存储目录迁移流程步骤(0个评论)
    • 在mysql中使用存储过程批量新增测试数据流程步骤(0个评论)
    • php+mysql数据库批量根据条件快速更新、连表更新sql实现(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2017-06
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-01
    • 2018-05
    • 2018-10
    • 2018-11
    • 2020-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2021-02
    • 2021-04
    • 2021-07
    • 2021-08
    • 2021-11
    • 2021-12
    • 2022-02
    • 2022-03
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客