前言

若果大家刚使用EntityFramework
Core作为ORM框架的话,想必都会碰着数据库迁移的有些题目。

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

在意目的框架接纳的是.NET Core 2.0而不是.NET
Standard 2.0。

AspNetCore – MVC实战体系目录

**. www.997755.com,爱留图网站诞生**

. 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也许存在的一个问题,当第四回索要在新创立的类库中动用反向工程变更实体模型的时候,如果您不设置该类库为开端项目,这会提示错误没办法生成成功的;我蒙受的时候用了众多措施尝试解决问题,甚至以为何东武汉错了,结果在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

www.997755.com 1

谬误提醒:

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

焚林而猎办法:

  在档次文件Light.Repository.csproj中添加以下节点

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

再一次履行上面的下令,假如出现了EF
Core的表明(一头蓄势待发的野马)表示早已成功

www.997755.com 2

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

dotnet ef migrations add InitLightDB

www.997755.com 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步骤的吩咐,报错新闻如下:

www.997755.com 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提姆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);
        }
    }

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

www.997755.com 5

事业有成唤醒:

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

并且类库上面会生成Migrations文件夹以及有关的迁移文件

www.997755.com 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 来读取出配置文件中配置的连接串,当然如果得以你也可以间接在此处吧连接串写死都行,那里截图突显下安插文件的层级关系:

www.997755.com 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

www.997755.com 8

经过VS的SQL
Server资源管理器查看生成数据库的协会,其中__EFMigrationsHistory为每便迁移的记录表

www.997755.com 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);
            });
        }

下一场同样拔取方面的两条命令重新迁移并更新数据库结构

www.997755.com 10

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

www.997755.com 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文件的节点名称一致就行了,然后在ConfigureService(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来说还从未达到可以调整数据库生成字段的逐一,然则我们仍旧得以修改迁移文件的实业性质的各类来达到大家想要的法力。上边是我调动过后再也生成的表,是还是不是看出来和方面的有如何两样,一图胜万语:

www.997755.com 12

 c)、最后一步,自己出手试试看:成立一个SeedData迁移文件来添加数据库的启幕数据。:)

4、最后

EF
Core的强大远不止那些,还有越来越多的选用方式等着大家去发现,去探索。每一天升高一点点,是件很欢腾的政工!

相关文章