• ASP.NET Core 3.1系列(15)——Entity Framework Core之DB First


    1、前言

    本文开始介绍一些关于Entity Framework Core的内容。在EFCore中,常用的为DB First模式和Code First模式,下面就来介绍一下如何在EFCore中使用DB First模式生成实体类和数据库上下文。

    2、创建测试数据库

    SQL Server中新建一个数据库Dao,执行如下语句,创建CountryProvince数据表。

    USE [Dao]
    GO
    
    /****** Object:  Table [dbo].[Country]    Script Date: 2022/11/30 8:52:23 ******/
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE TABLE [dbo].[Country](
    	[Id] [int] IDENTITY(1,1) NOT NULL,
    	[CountryName] [nvarchar](20) NULL,
     CONSTRAINT [PK_Country] 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    USE [Dao]
    GO
    
    /****** Object:  Table [dbo].[Province]    Script Date: 2022/11/30 8:53:00 ******/
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE TABLE [dbo].[Province](
    	[Id] [int] IDENTITY(1,1) NOT NULL,
    	[ProvinceName] [nvarchar](20) NULL,
     CONSTRAINT [PK_Province] 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    运行结果如下图所示:

    在这里插入图片描述

    3、引入EFCore相关组件

    创建一个Web API项目,使用NuGet引入如下四个组件,这里全部选择3.1.31版本:

    Microsoft.EntityFrameworkCore
    Microsoft.EntityFrameworkCore.SqlServer
    Microsoft.EntityFrameworkCore.Design
    Microsoft.EntityFrameworkCore.Tools
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    4、生成实体类和数据库上下文

    EFCore中,使用DB First模式生成实体类和数据库上下文时需要使用Scaffold-DbContext命令,该命令的格式如下所示:

    Scaffold-DbContext [-Connection] <String> [-Provider] <String> [-OutputDir <String>] [-ContextDir <String>] [-Context <String>] [-Schemas <String[]>] [-Tables <String[]>] [-DataAnnotations] [-UseDatabaseNames] [-Force] [-Project <String>] [-StartupProject <String>][<CommonParameters>]
    
    • 1

    Scaffold-DbContext命令中的参数说明如下表所示:

    名称含义
    -Connection指定数据库的连接字符串
    -Provider指定要使用的提供程序。例如Microsoft.EntityFrameworkCore.SqlServer
    -OutputDir指定用于输出类的目录。如果省略,则使用顶级项目目录
    -ContextDir指定存放DbContext的目录
    -Context指定生成的DbContext类的名称
    -Schemas指定要为其生成类的模式
    -Tables指定要为其生成类的表
    -DataAnnotations使用DataAnnotation属性在可能的情况下配置模型
    -Force强制脚手架覆盖现有文件
    -Project指定实体类和数据库上下文存放在的项目名称
    -StartupProject指定启动项目名称

    打开NuGet控制台,输入如下命令:

    Scaffold-DbContext -Connection "Data Source=DSF-PC;Initial Catalog=Dao;User ID=sa;Password=123456;" -Provider Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -ContextDir Context -Context DaoDbContext
    
    • 1

    运行结果如下图所示,可以发现已经创建了实体类CountryProvince和数据库上下文类DaoDbContext。到此为止,我们已经可以通过Scaffold-DbContext命令生成实体类和数据库上下文了。

    在这里插入图片描述

    5、Scaffold-DbContext命令中一些参数的含义及作用

    在上面的代码中,我们对Scaffold-DbContext命令中的一些关键参数进行了设置:

    • -OutputDir Models:存放实体类的文件夹名称为Models
    • -ContextDir Context:存放数据库上下文的文件夹名称为Context
    • -Context DaoDbContext:数据库上下文的名称为DaoDbContext

    其实Scaffold-DbContext命令中还包括一些很有用的其他参数,下面举例说明。

    5.1、只对数据库中的某些表生成实体类该怎么做?

    在某些情况下,我们并不希望数据库中所有的表都生成实体类,而是只将某些需要的表生成实体类即可,此时就需要对-Tables参数进行设置,下面的代码只对Country表生成实体类,而Province表则不生成实体类。

    Scaffold-DbContext -Connection "Data Source=DSF-PC;Initial Catalog=Dao;User ID=sa;Password=123456;" -Provider Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -ContextDir Context -Context DaoDbContext -Tables "Country"
    
    • 1

    在这里插入图片描述

    5.2、如何生成实体类字段的数据注解?

    当前的实体类字段并不包含数据注解,如下图所示:

    在这里插入图片描述
    在这里插入图片描述
    如果需要生成数据注解,只需要添加一个-DataAnnotations参数即可,代码如下:

    Scaffold-DbContext -Connection "Data Source=DSF-PC;Initial Catalog=Dao;User ID=sa;Password=123456;" -Provider Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -ContextDir Context -Context DaoDbContext -DataAnnotations
    
    • 1

    可以发现实体类字段已经生成了对应的数据注解。

    在这里插入图片描述
    在这里插入图片描述

    5.3、数据库被修改后如何更新实体类和数据库上下文?

    当前工程中的实体类和数据库上下文如下图所示:

    在这里插入图片描述
    下面对数据库进行一些修改。首先在Dao数据库中新增一张City表,代码如下:

    USE [Dao]
    GO
    
    /****** Object:  Table [dbo].[City]    Script Date: 2022/11/30 9:30:54 ******/
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE TABLE [dbo].[City](
    	[Id] [int] IDENTITY(1,1) NOT NULL,
    	[CityName] [nvarchar](20) NULL,
    	[CreateTime] [datetime] NULL,
     CONSTRAINT [PK_City] 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述
    然后在Country表和Province表中新增一个字段CreateTime,代码如下:

    alter table Country add [CreateTime] datetime null
    alter table Province add [CreateTime] datetime null
    
    • 1
    • 2

    在这里插入图片描述
    现在对数据库的修改已经完成,下面就需要对实体类和数据库上下文进行更新了,我们只需要在Scaffold-DbContext命令后面加上-Force参数即可,它可以帮助我们重新生成实体类和数据库上下文并覆盖原有文件。

    Scaffold-DbContext -Connection "Data Source=DSF-PC;Initial Catalog=Dao;User ID=sa;Password=123456;" -Provider Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -ContextDir Context -Context DaoDbContext -DataAnnotations -Force
    
    • 1

    可以发现覆盖后的文件已经新增了City实体类,CountryProvince实体类也都新增了CreateTime字段。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    5.4、分层项目中如何在其他类库中生成实体类和数据库上下文?

    在实际开发过程中,很多项目都会进行分层操作,例如新建一个App.Models类库用来存放实体类和数据库上下文,如下图所示:

    在这里插入图片描述
    如果想在App.Models类库中生成实体类和数据库上下文也很简单,只需要按照如下步骤操作即可,首先在App.Models中使用NuGet引入EFCore的相关组件,如下所示:

    Microsoft.EntityFrameworkCore
    Microsoft.EntityFrameworkCore.SqlServer
    Microsoft.EntityFrameworkCore.Design
    Microsoft.EntityFrameworkCore.Tools
    
    • 1
    • 2
    • 3
    • 4

    然后生成一下解决方案:

    在这里插入图片描述
    最后在Scaffold-DbContext命令中设置-Project-StartupProject参数,代码如下:

    Scaffold-DbContext -Connection "Data Source=DSF-PC;Initial Catalog=Dao;User ID=sa;Password=123456;" -Provider Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -ContextDir Context -Context DaoDbContext -DataAnnotations -Force -Project App.Models -StartupProject App.Models
    
    • 1

    可以发现在App.Models项目中已经生成了实体类和数据库上下文。

    在这里插入图片描述

    6、注入数据库上下文

    现在实体类和数据库上下文都有了,接下来只需要在Controller中将其注入即可。首先在appsettings.json文件中配置数据库连接字符串,代码如下:

    {
        "Logging": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft": "Warning",
                "Microsoft.Hosting.Lifetime": "Information"
            }
        },
        "AllowedHosts": "*",
        "ConnectionStrings": {
            "ConnectionString": "Data Source=DSF-PC;Initial Catalog=Dao;User ID=sa;Password=123456;"
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    然后在Startup.cs文件中添加数据库上下文,代码如下所示:

    using App.Context;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    
    namespace App
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                // 添加控制器
                services.AddControllers();
    
                // 添加数据库上下文
                services.AddDbContext<DaoDbContext>(options =>
                {
                    options.UseSqlServer(Configuration.GetConnectionString("ConnectionString"));
                });
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                app.UseHttpsRedirection();
                app.UseRouting();
                app.UseAuthorization();
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    最后新建一个控制器CountryController.cs,将DaoDbContext注入即可,代码如下:

    using App.Context;
    using App.Models;
    using Microsoft.AspNetCore.Mvc;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace App.Controllers
    {
        [Route("api/[controller]/[action]")]
        [ApiController]
        public class CountryController : ControllerBase
        {
            protected readonly DaoDbContext _dbContext;
    
            /// 
            /// 构造函数
            /// 
            /// 
            public CountryController(DaoDbContext dbContext)
            {
                _dbContext = dbContext;
            }
    
            /// 
            /// 添加实体集合
            /// 
            /// 
            [HttpGet]
            public ActionResult<string> Add()
            {
                List<Country> list = new List<Country>
                {
                    new Country { CountryName = "中国" },
                    new Country { CountryName = "美国" },
                    new Country { CountryName = "俄罗斯" }
                };
                _dbContext.Set<Country>().AddRange(list);
                _dbContext.SaveChanges();
                return "添加实体成功";
            }
    
            /// 
            /// 获取实体集合
            /// 
            /// 
            [HttpGet]
            public ActionResult<List<Country>> Get()
            {
                return _dbContext.Set<Country>().ToList();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    执行Add方法后,运行结果如下图所示:

    在这里插入图片描述
    执行Get方法后,运行结果如下图所示:

    在这里插入图片描述

    7、结语

    本文主要介绍了一些关于EFCoreDB First开发模式的内容,对于Scaffold-DbContext命令中其他的参数含义及作用,有兴趣的同志也可以自行深入研究。如果你参与的项目之前就已经存在数据库,那么选用DB First模式可能会更加方便友好。

  • 相关阅读:
    六、Big Data Tools安装
    流动舞台车改装设计(说明书+任务书+开题报告+评分表+cad图纸)
    PacBio全长扩增子测序发现酵母益生菌可提高黑山羊免疫力
    【ACWing 算法基础】KMP
    一次实战压测流程及问题梳理
    【高级篇 / ZTNA】(7.0) ❀ 05. 域用户自动安装 FortiClient (上) ❀ FortiGate 防火墙
    Android岗位面试精准拿offer,看字节大厂面试流程如何突破?
    【WPF系列】- XAML语法规范
    Python 在Word中创建表格并填入数据、图片
    线程池如何优雅关闭
  • 原文地址:https://blog.csdn.net/HerryDong/article/details/128091994