Core迁移数据库到SQL,MVC实战体系

by admin on 2018年12月31日

前言

只要我们刚使用EntityFramework
Core作为ORM框架的话,想必都会遇上数据库迁移的一部分题目。

起先我是在ASP.NET
Core的Web项目中开展的,但后来意识放在这里并不是很客观,一些关于数据库的迁徙,比如新增表,字段,修改字段类型等等,不应当和最上层的Web项目所波及,数据的动迁文件放到这里也倍感有些多余,有点乱乱的感觉,所以才想着单独出来由专门的序列进展管理会相比好,也相比清楚!

瞩目目的框架采纳的是.NET Core 2.0而不是.NET
Standard 2.0。

AspNetCore – MVC实战系列目录

**. 亚洲必赢手机入口,爱留图网站诞生**

. git源码:https://github.com/shenniubuxing3/LovePicture.Web

**. AspNetCore –
MVC实战序列(一)之Sqlserver表映射实体模型
**

. AspNetCore-MVC实战体系(二)之通过绑定邮箱找回密码

. [AspNetCore-MVC实战体系(三)之个人主题](http://www.cnblogs.com/wangrudong003/p/6793529.html)

**AspNetCore-MVC实战序列(四)之账户设置**

本章开篇先简单介绍下近年来两周自己使用业余时间做的一个图形收集网站,当然这些是靠用户自己上传来收集不是去抓某些个网站的图纸,这样没意义,那里自己取名为“爱留图”;该网站的简约介绍我们可以参照下上篇的情节爱留图的落地,这里打算通过一些列的博客讲解怎么着一步步利用aspnetcore的mvc来支付,希望我们可以欣赏;

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; }
    }

Sqlserver表映射实体模型(反向工程变更实体模型)

首先,咋们需要在sqlserver中开创一张用户表To_UserInfo,那里自己尽可能简单取一些性能作为字段,以下是表结构SQL:

USE [LovePicture.Db]
GO

/****** Object:  Table [dbo].[To_UserInfo]    Script Date: 2017/4/25 17:30:53 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[To_UserInfo](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [UserName] [nvarchar](50) NOT NULL,
    [UserPwd] [nvarchar](50) NOT NULL,
    [Email] [nvarchar](50) NULL,
    [NickName] [nvarchar](20) NULL,
    [Tel] [nvarchar](20) NULL,
    [Sex] [bit] NOT NULL,
    [Introduce] [nvarchar](200) NULL,
    [HeadPhoto] [nvarchar](200) NULL,
    [Birthday] [nvarchar](20) NULL,
    [Addr] [nvarchar](200) NULL,
    [Blog] [nvarchar](200) NULL,
    [Status] [int] NOT NULL,
    [CreateTime] [datetime] NOT NULL,
    [LoginTime] [datetime] NULL,
    [Ips] [nvarchar](50) NULL,
    [LevelNum] [int] NOT NULL,
 CONSTRAINT [PK_To_UserInfo] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

字段的情趣不必太明了,重倘使上学怎么变卦实体;先创立一个类库LovePicture.Model,由于此地自己打算动用EF
Core(全名:entity framework
core),由此需要对这些类库安装相应的nuget包:

 Microsoft.EntityFrameworkCore.Design 

 Install-Package
Microsoft.EntityFrameworkCore.SqlServer 

 Install-Package
Microsoft.EntityFrameworkCore.Tools 

 Install-Package
Microsoft.EntityFrameworkCore.SqlServer.Design 

留意啦是4个包,netcore官网给出的只有前面3个包没有第一个,有实际经历得出如果你不添加第一个包,那么由数据库来扭转实体模型的时候会提醒错误,这里自己就不截图错误音信了有趣味的爱人可尝试;来到此处咋们还需要通过vs控制台输入执行命令:

 Scaffold-DbContext “Server=127.0.0.1,1431;User
Id=sa;Password=123123;Database=LovePicture.Db;” Microsoft.EntityFrameworkCore.SqlServer
-OutputDir Models 

简单的讲说下参数吧:

. Scaffold-DbContext:执行命令

. Server=…:数据库链接字符串

. -OutputDir Models:输出实体到名称为Models的公文夹中

个人领会的注意事项:

vs2017或者存在的一个题材,当第一次索要在新创立的类库中行使反向工程变更实体模型的时候,如若您不设置该类库为开头项目,这会提醒错误没法生成成功的;我碰着的时候用了累累主意尝试解决问题,甚至以为何东布Rhys托错了,结果在Git的题目基本找到了有关题材的答疑,仅仅只需要设置下启动项就能解决,真实让自己吃惊吗。

到那里倘使你遵照以上我列举的步调操作,应该不会冒出太大的题材可以通过sqserver数据库生成实体成功,当然不保证其他特殊的事态吧;

1、问题会聚

率先要保证仓储类库中早就引入以下六个Nuget包,没有的话请使用包管理器举行设置。不提出直接引入原包:Microsoft.AspNetCore.All,按需引入即可

Install-Package Microsoft.EntityFrameworkCore.SqlServer

Install-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

亚洲必赢手机入口 1

不当指示:

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

解决办法:

  在品种文件Light.Repository.csproj中添加以下节点

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

重新履行下边的命令,要是出现了EF
Core的标志(一头蓄势待发的野马)表示曾经打响

亚洲必赢手机入口 2

 b)、执行以下命令举办搬迁

dotnet ef migrations add InitLightDB

亚洲必赢手机入口 3

荒唐指示:

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步骤的授命,报错音信如下:

亚洲必赢手机入口 4

荒唐提醒:

  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导致的,接下去我们按照提醒,实现一个IDesign提姆(Tim)eDbContextFactory<LightContext>试试

釜底抽薪措施:

  创制一个与DbContext同一目录下的Design提姆eDbContextFactory文件,然后实现接口中的方法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);
        }
    }

 再次实施迁移命令,终于不负众望了。

亚洲必赢手机入口 5

成功唤醒:

  Done. To undo this action, use ‘ef
migrations remove’

再者类库下边会生成Migrations文件夹以及有关的动迁文件

亚洲必赢手机入口 6

在MVC中使用生成的实体模型

率先,通过vs2017开立个Aspnetcore的Mvc项目本身取名为LovePicture.Web,我们要询问的是netcore项目基本上都是由此nuget包来引入其他零件,不过强大的vs可以让大家直接通过:右键web项目的“看重项”-》添加引用-》解决方案-》选拔任何体系的名号,以此来添加对其他类另外依靠(重假如新的vs版本所以废话一下);

有了依靠关系我们先来改造一下因此反向工程变动的DbContext代码来满足我们在Web中Mvc的采取;打开模型类库中的LovePicture_DbContext.cs文件,可以看出我们相比熟知类似于任何EF框架版本的布局,这里我们只需要自动生成的LovePicture_DbContext构造函数删除掉,然后再次添加一个这样的构造函数:

1 public LovePicture_DbContext(DbContextOptions<LovePicture_DbContext> options) : base(options) { }

如此就能吧DbContext当做注入服务提供给引入这么些类库的系列选取了,我们也无非只需要在Web项目中的Startup.cs文件的ConfigureServices方法中增长依赖注入即可:

 1 //添加数据库上下文
 2             services.AddDbContext<LovePicture_DbContext>(b =>
 3             {
 4 
 5                 var dbLink = Configuration.GetSection("MoSelfSetting:DbLink").Value;
 6                 if (string.IsNullOrWhiteSpace(dbLink)) { throw new Exception("未找到数据库链接。"); }
 7 
 8                 b.UseSqlServer(dbLink);
 9 
10             });

这边由于链接数据库的话需要有一个一体系,这里通过DbContextOptionsBuilder的UseSqlServer扩大方法来传递,字符串的来源这里我安排在appsettings.json配置文件中的,由此可以很便利的通过 Configuration.GetSection(“MoSelfSetting:DbLink”).Value 来读取出配置文件中布置的连日串,当然如若能够你也足以一贯在此地吧连接串写死都行,这里截图呈现下安排文件的层级关系:

亚洲必赢手机入口 7

好了有了以上的配备,咋们就可以在MVC的Controller中很好的应用DbContext了,这里透过构造函数注入的不二法门接纳:

1     private readonly LovePicture_DbContext _db;
2         public HomeController(LovePicture_DbContext db)
3         {
4             _db = db;
5         }

到这里Controller中就可知利用DbContext了,大家得以在Action中直接通过各种EF的操作方法来对数据库执行读写命令;

2、小试迁移命令

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

dotnet ef database update

亚洲必赢手机入口 8

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

亚洲必赢手机入口 9

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);
            });
        }

接下来同样接纳方面的两条命令重新迁移并革新数据库结构

亚洲必赢手机入口 10

着眼数据库表结构早已更新

亚洲必赢手机入口 11

 同理添加字段,删除字段都是千篇一律的搬迁操作,依然很便宜的

通过IOptions<T>使用自定义配置音信

因为前边作品内容涉嫌到用户上传头像等新闻,所以需要有些可配置的音讯(如:上传路径,链接字符串),所以这边需要有读取我们自定义配置节点音讯的操作;这里运用现成的appsettings.json文件来布局信息,这里我的配置内容如:

 1 {
 2   "Logging": {
 3     "IncludeScopes": false,
 4     "LogLevel": {
 5       "Default": "Warning"
 6     }
 7   },
 8   "MoSelfSetting": {
 9     //图片内容路径
10     "UpHeadPhotoPath": "D:\\F\\学习\\vs2017\\netcore\\LovePicture.Web\\wwwroot\\upfile\\headphoto",
11     "ViewHeadPhotoPath": "/upfile/headphoto",
12     //头像路径
13     "UpContentPhotoPath": "D:\\F\\学习\\vs2017\\netcore\\LovePicture.Web\\wwwroot\\upfile\\contentphoto",
14     "ViewContentPhotoPath": "/upfile/contentphoto",
15     //邮箱模板
16     "EmailTplPath": "D:\\F\\学习\\vs2017\\netcore\\LovePicture.Web\\wwwroot\\tpl",
17     //链接字符串
18     "DbLink": "Server=127.0.0.1,1431;User Id=sa;Password=123123;Database=LovePicture.Db;"
19   }
20 }

要取得这些文件的自定义信息,我们需要成立一个对应属性名称的实业MoSelfSetting:

 1 /// <summary>
 2     /// 自定义配置
 3     /// </summary>
 4     public class MoSelfSetting
 5     {
 6         /// <summary>
 7         /// 头像图片保存地址 
 8         /// </summary>
 9         public string UpHeadPhotoPath { get; set; }
10 
11         /// <summary>
12         /// 头像图片访问地址 
13         /// </summary>
14         public string ViewHeadPhotoPath { get; set; }
15 
16         /// <summary>
17         /// 内容图片保存地址 
18         /// </summary>
19         public string UpContentPhotoPath { get; set; }
20 
21         /// <summary>
22         /// 查看内容图片保存地址 
23         /// </summary>
24         public string ViewContentPhotoPath { get; set; }
25 
26         /// <summary>
27         /// 邮件模板文件夹路径 
28         /// </summary>
29         public string EmailTplPath { get; set; }
30 
31         /// <summary>
32         /// 数据库链接
33         /// </summary>
34         public string DbLink { get; set; }
35     }

实业类属性名称和appsettings.json文件的节点名称相同就行了,然后在Configure瑟维斯(Service)s方法中丰裕配置文件设置:

1  //设置自定义配置信息  
2             services.Configure<MoSelfSetting>(Configuration.GetSection("MoSelfSetting"));

单独只需要采用这段代码,就能完成从json配置文件的数量到实体数据的中转,比往日确实方便了成千上万;然后同样通过在Controller中采纳IOptions<T>来注入那一个布局文件实体到Controller中:

 1  private readonly LovePicture_DbContext _context;
 2         private readonly MoSelfSetting _selfSetting;
 3         private readonly IMemoryCache _cache;
 4 
 5         public MemberController(LovePicture_DbContext context, IOptions<MoSelfSetting> selfSetting, IMemoryCache cache)
 6         {
 7             _context = context;
 8             _selfSetting = selfSetting.Value;
 9             _cache = cache;
10         }

最后经过IOptions<T>.Value形式,直接就能够得到出富有配置文件信息的实业数据了;这里就不再写测试用例了,这么些都会在前面一些列章节中应用到,希望本篇著作能给您好的收获,假设可以不妨点个“赞”,谢谢。

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来说还一直不直达可以调动数据库生成字段的依次,但是大家仍旧得以修改迁移文件的实业性质的顺序来达到我们想要的效应。上面是自身调动过后再行生成的表,是不是看出来和方面的有怎么着两样,一图胜万语:

亚洲必赢手机入口 12

 c)、末了一步,自己动手试试看:创造一个SeedData迁移文件来添加数据库的始发数据。:)

4、最后

EF
Core的强大远不止这多少个,还有更多的运用方法等着大家去发现,去研究。天天进步一点点,是件很喜悦的作业!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图