• ASP.NET Core 3 高级编程(第8版) 学习笔记 03


    本篇介绍原书的第 18 章,为 19 章 Restful Service 编写基础代码。本章实现了如下内容:
    1)使用 Entity Framework Core 操作 Sql Server 数据库
    2)Entity Framework Core 数据库迁移和使用种子数据的方法
    3)使用中间件 (middleware) 来配置请求管道 (request pipeline)

    Nuget 包

    为了运行本章代码,需要下面的三个包:

    Microsoft.EntityFrameworkCore.SqlServer --version 3.1.1
    Microsoft.EntityFrameworkCore.Design --version 3.1.1
    Microsoft.EntityFrameworkore.Tool --version 3.1.1
    
    • 1
    • 2
    • 3

    数据模型

    创建 Products, Category 和 Suppliers 三个实体模型:

    namespace WebApp.Models
    {
        public class Category
        {
            public long CategoryId { get; set; }
            public string Name { get; set; }
    
            public IEnumerable<Product> Products { get; set; }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    namespace WebApp.Models
    {
        public class Supplier
        {
            public long SupplierId { get; set; }
            public string Name { get; set; }
            public string City { get; set; }
    
            public IEnumerable<Product> Products { get; set; }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    namespace WebApp.Models
    {
        public class Product
        {
            public long ProductId { get; set; }
            public string Name { get; set; }
            public decimal Price { get; set; }  
    
            public long CategoryId { get; set; }
            public Category Category { get; set; }
    
            public long SupplierId { get; set; }
            public Supplier Supplier { get; set; }  
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    创建 DbContext 类

    using Microsoft.EntityFrameworkCore;
    
    namespace WebApp.Models
    {
        public class DataContext : DbContext
        {
            public DataContext(DbContextOptions<DataContext> opts) : base(opts) { }
    
            public DbSet<Product> Products { get; set; }
            public DbSet<Category> Categories { get; set; }
            public DbSet<Supplier> Suppliers { get; set; }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    种子数据

    using Microsoft.EntityFrameworkCore;
    using System.Linq;
    
    namespace WebApp.Models
    {
        public class SeedData
        {
            public static void SeedDatabase(DataContext context)
            {
                context.Database.Migrate();
                // 只有在空的时候才填充数据
                if (context.Products.Count() == 0 && context.Suppliers.Count() == 0 && context.Categories.Count() == 0) {
    
                    // 供应商
                    var s1 = new Supplier
                    {
                        Name = "Splash Dudes",
                        City = "San Jose"
                    };
    
                    var s2 = new Supplier
                    {
                        Name = "Soccer Town",
                        City = "Chicago"
                    };
    
                    var s3 = new Supplier 
                    { 
                        Name = "Chess Co",
                        City = "New York"
                    };
    
                    // Category
                    var c1 = new Category { Name = "Watersports" };
                    var c2 = new Category { Name = "Soccer" };
                    var c3 = new Category { Name = "Chess" };
    
                    context.Products.AddRange(
                       new Product { Name = "Kayak", Price = 275, Category = c1, Supplier = s1} ,
                       new Product { Name = "LifeJacket", Price = 48.95m, Category = c1, Supplier = s1} , 
                       new Product { Name = "Soccer ball", Price = 19.50m, Category= c2, Supplier = s2} ,
                       new Product { Name = "Corner Flags", Price = 34.95m, Category= c2, Supplier = s2} ,
                       new Product { Name = "Stadium", Price = 79500, Category= c2, Supplier = s2} ,
                       new Product { Name = "Thinking Cap", Price = 16, Category= c3, Supplier = s3} ,
                       new Product { Name = "Unsteady Chair", Price = 29.95m, Category= c3, Supplier = s3} ,
                       new Product { Name = "Human Chess Board", Price = 75, Category= c3, Supplier = s3} ,
                       new Product { Name = "Bling-Bling King", Price = 1200, Category= c3, Supplier = s3} 
                    );
    
                    context.SaveChanges();
                }
            }
        }
    }
    
    • 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
    • 53
    • 54

    数据库连接字符串

    使用 Sql Server LocalDB,将数据库连接字符串写在 appsettings.json 文件。

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information",
          "Microsoft.EntityFrameworkCore": "Information"
        }
      },
      "AllowedHosts": "*",
      "ConnectionStrings" : {"ProductConnection" : "Server=(localdb)\\MSSQLLocalDB;Database=Products;MultipleActiveResultSets=True"}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    配置 Entity Framework Core

    在 Startup.cs 的 Configure() 方法中进行配置:

    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using WebApp.Models;
    
    namespace WebApp
    {
        public class Startup
        {
            public Startup(IConfiguration config)
            {
                Configuration = config;
            }
    
            public IConfiguration Configuration { get; set; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddDbContext<DataContext>(opts =>
                {
                    opts.UseSqlServer(Configuration["ConnectionStrings:ProductConnection"]);
                    //opts.EnableSensitiveDataLogging(true);
                });
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext context)
            {         
    
                if (env.IsDevelopment()) {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseRouting();
                
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapGet("/", async context =>
                    {
                        await context.Response.WriteAsync("Hello World!");
                    });
                });
    
                SeedData.SeedDatabase(context);
            }
        }
    }
    
    • 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
    • 53
    • 54
    • 55
    • 56
    • 57

    注意:Configure() 方法在默认代码的基础上增加了 DbContext 参数,目的是启动的时候自动运行向数据库添加种子数据。

    数据库迁移

    打开 Package Manager Console (Tools > Nuget Package Manager > Package Manager Console),运行下面两个命令:

    Add-migration initDatabae
    update-database
    
    • 1
    • 2

    Add-migration 命令将创建迁移脚本
    update-database 将未提交的变化提交到数据库。

    运行之后,使用 SQL Server Object Explorer (View > SQL Server Object Explore)可以看到,数据库和表都已经正确创建。

    使用中间件配置请求管道

    希望实现的效果是 Http Get 请求 /test 能返回三张表的数据条数。

    创建 TestMiddleware 中间件:

    using Microsoft.AspNetCore.Http;
    using System.Linq;
    using System.Threading.Tasks;
    using WebApp.Models;
    
    namespace WebApp
    {
        public class TestMiddleware
        {
            private RequestDelegate nextDelegate;
    
            public TestMiddleware(RequestDelegate nextDelegate)
            {
                this.nextDelegate = nextDelegate;
            }
    
            public async Task Invoke(HttpContext context, DataContext dataContext)
            {
                if (context.Request.Path == "/test") {
                    await context.Response.WriteAsync($"There are {dataContext.Products.Count()} prodcts.\n");
                    await context.Response.WriteAsync($"There are {dataContext.Categories.Count()} categories.\n");
                    await context.Response.WriteAsync($"There are {dataContext.Suppliers.Count()} suppliers.\n");
                } else {
                    await nextDelegate(context);
                }
            }
        }
    }
    
    • 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

    在 Startup.cs 文件中配置中间件。

    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using WebApp.Models;
    
    namespace WebApp
    {
        public class Startup
        {
            public Startup(IConfiguration config)
            {
                Configuration = config;
            }
    
            public IConfiguration Configuration { get; set; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddDbContext<DataContext>(opts =>
                {
                    opts.UseSqlServer(Configuration["ConnectionStrings:ProductConnection"]);
                    //opts.EnableSensitiveDataLogging(true);
                });
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext context)
            {         
    
                if (env.IsDevelopment()) {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseRouting();
                app.UseMiddleware<TestMiddleware>();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapGet("/", async context =>
                    {
                        await context.Response.WriteAsync("Hello World!");
                    });
                });
    
                SeedData.SeedDatabase(context);
            }
        }
    }
    
    
    • 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
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    源码

    pro asp.net core 3 notes: 《ASP.NET Core 3高级编程(第8版)》学习笔记

  • 相关阅读:
    debian中vim的使用
    100天精通Python(爬虫篇)——第44天:requests库大总结
    C++ 模板进阶使用
    【WINDOWS / DOS 批处理】if命令参数详解(二)
    CSRF和XSS是什么?
    Elasticsearch:使用 Low Level Java 客户端来创建连接 - Elastic Stack 8.x
    了解mybatis
    Java面试核心知识点----Java面试题合集最新版
    OptiX8入门(一)optixHello
    5800交点正反算坐标(可计算不对称缓和曲线)
  • 原文地址:https://blog.csdn.net/stone0823/article/details/137999906