Minimal API in .NET 6 Using Dapper and SQL - Minimal API Project

9 篇文章 0 订阅

快捷键

prop public int MyProperty { get; set; } [property]

ctor 创建一个构造函数(constructor)

part1

数据库、存储过程处理

最小的API:这里新建项目的时候没有用控制器
在这里插入图片描述

创建数据库文件夹UserDB
在这里插入图片描述

数据表格user设计过程中:
在这里插入图片描述

​ 表格创建完毕之后,开始创建一些**StoredProcedures 存储过程来使表格中存在数据。这里使用存储过程是因为 他们是我们预先就编写好的逻辑,而且我们试图对其中的实际业务逻辑做太多的事情。一方面它里面已经包括了我们对数据的四种基本运算,另一方面他们是已经写好的存储过程,所以他比我们仅仅运行我们的sql语句要快一点**。另一件事是,当sql 中出现性能问题时,很容易通过存储过程找出问题所在(因为日志文件中就包含了存储过程名称,而不是大而长的SQL语句,通过这种方式我们就可以很简单的找出是谁调用了该sql语句,)。
在这里插入图片描述
在这里插入图片描述

在我们创建了基本的存储过程之后,我们就可以新建一个脚本(后期部署脚本Script.PostDeployment.sql),它在我们部署之后运行。但是我也要注意后期部署脚本只能部署一个

if not exists (select 1 from dbo.[User])  --不存在就输出n行1,并执行下面的代码块对空的数据表进行初始数据填充
begin
	insert into dbo.[User] (FirstName, LastName)
	values ('Tim', 'Corey'),
	('Sue', 'Storm'),
	('John', 'Smith'),
	('Mary', 'Jones');
end

然后将其发布(右键文件点击发布)生成一个UserDB.publish.xml发布文件。
在这里插入图片描述

点击发布,即可运行存储过程的SQL语句。
在这里插入图片描述

即可在MSSQ本地数据库中生成MinimalAPIUserDB

向页面应用添加模型

在本教程中,添加了用于管理数据库中的电影的====。 应用的模型类使用**Entity Framework Core (EF Core)** 来处理数据库。 EF Core 是一种对象关系映射器 (ORM),可简化数据访问。 首先要编写模型类,然后 EF Core 将创建数据库。

​ 模型类称为 POCO 类(源自“简单传统 CLR 对象” ),因为它们与 EF Core 没有任何依赖关系。 它们定义数据库中存储的数据属性。

所以 添加模型实际上就是添加新的类

添加数据模型—类
  1. 在“解决方案资源管理器”中,右键单击“MinimalAPIDemo”项目 >“添加”>“新建文件夹”。 将该文件夹命名为 Models注册一个免费试用帐户。
  2. 右键单击 Models 文件夹。 选择“添加”>“类” 。 将类命名“UserModel”。
  3. UserModel 类添加以下属性:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataAccess.Models;

public class UserModel
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

与数据库进行对话

从sql server 中获取数据或将其发送给sql serve。

①安装:

将使用三个NuGet 包(dapper、System.Data.SqlClient、Microsoft.Extensions.Configuration.Abstractions)。

安装Microsoft.Extensions.Configuration.Abstractions将允许我们与appsettings.json或我们项目加载的其他地方进行交谈

②做一些数据访问或者与sql serve交谈。

​ 在DbAccess文件夹下新建数据库访问sql文件SqlDataAccess.cs,在Data文件夹下新建用户数据文件UserData.cs。

在这里我们是通过dapper与SQL进行对话,所以我们就创建了一个通用的对话处理类,这样与SQL的所有对话和设置都由该类处理而直接可以用于其他对数据库的操作。(中间代理商)

依赖关系注入的快捷方式
在这里插入图片描述

SqlDataAccess代码讲解

①实现依赖关系注入
 private readonly IConfiguration _config;  /*变量重命名,依赖注入系统的私有变量_context*/

    public SqlDataAccess(IConfiguration config)
    {
        _config = config; /*构造函数使用[依赖关系注入]将 `IConfiguration` 数据库上下文注入到控制器中*/
    }

​ 这里自动生成的关于config是没有带下划线的,所以我们需要手动的将其修改,实现一个依赖注入系统的私有变量。而我们这个文件下面将要发生的事情都是通过依赖注入来实现的。

IConfiguration:从secrets.json appsettings.development.json.production.json,ppsettings.json去获取设置。还可以从环境变量和其他位置获取信息。

​ 在.NET Core中**读取配置是通过IConfiguration接口,它存在于Microsoft.Extensions.Configuration.Abstractions项目中。当我们通过IConfiguration获取配置时**,其实就是倒序遍历IConfigurationBuilder加载进来的配置源。所有加载到程序中的配置源,其本质还是存储在Provider里面一个类型为IDictionary<string, string> Data属性中。由此推论: 当通过IConfiguration获取配置时,就是通过各个Provider的Data读取!

​ IConfiguration 是用来加载配置值的,可以加载内存键值对、JSON或XML配置文件,我们通常用来加载缺省的appsettings.json .

②实现对数据的下载
    public async Task<IEnumerable<T>> LoadData<T, U>(
        string storedProcedure, /*存储过程*/
        U parameters,
        string connectionId = "Default")
    {
        using IDbConnection connection = new SqlConnection(_config.GetConnectionString(connectionId));

        return await connection.QueryAsync<T>(storedProcedure, parameters,
            commandType: CommandType.StoredProcedure);
    }

async:我们这里使用异步来处理的好处就是当方法在等待调用发生时,不会锁定用户界面。因此我们不会再调用SQL数据库时锁定用户界面。

​ 返回一个Task,这是**所有异步方法都应该做的(理解为约定熟成的,下面的SaveData()没有返回值但是他还是有这个Task,然后Task任务的类型是IEnumerable,他是我们使用的第一个泛型,T是我们想要返回的任何类型,在这里的话整个就是usermodel**(即为从数据库调用返回到SQL服务器的一组此模型,这里用用户模型来承接)

IEnumerable是命名空间( System.Collections.Generic 例如 ListDictionary)和其他 Stack 泛型集合(如 ObservableCollectionConcurrentStack)的基接口。是一个公开枚举数,该枚举数支持在指定类型的集合上进行简单迭代

  • 泛型数据—既可以传递任何类型的数据

可以接收任意的对象类型,而不存在类型转换的问题。

  • 泛型:是一种把明确类型的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,而这种参数类型可以用在类、方法和接口中,分别被称为泛型类泛型方法泛型接口
    注意:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。

  • T可以**随便写为任意标识**

3. 使用泛型的好处
  • 避免了类型强转的麻烦。
  • 它提供了编译期的类型安全,确保在泛型类型(通常为泛型集合)上只能使用正确类型的对象,避免了在运行时出现ClassCastException。

​ 泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种集合框架容器类,如:List、Set、Map。

@param <T> 这里解释下<T>中的T:
*           此处的T可以随便写为任意标识,常见的有T、E等形式的参数表示泛型
*           泛型在定义的时候不具体,使用的时候才变得具体。
*           在使用的时候确定泛型的具体数据类型。即在创建对象的时候确定泛型。

快捷方式:实现自适应
在这里插入图片描述

 using IDbConnection connection = new SqlConnection(_config.GetConnectionString(connectionId));

_config.GetConnectionString(connectionId):会去appsetting.json或者整个文件files去查找这个**包含connectionId关键字的ConnectionString**。connectionId的默认值为default,但是无论我们传给它什么connectionId字符串,他都放回他找到的实际连接字符串ConnectionString。

然后我们把这个得到的ConnectionString作为新的SQL连接字符串,创建一个SQL连接。

③实现对数据的上传

同理如上

public async Task SaveData<T>(
        string storedProcedure,
        T parameters,
        string connectionId = "Default")
{
        using IDbConnection connection = new SqlConnection(_config.GetConnectionString(connectionId));

        await connection.ExecuteAsync(storedProcedure, parameters,
            commandType: CommandType.StoredProcedure);
 }

由编写的类提取出一个抽象类

由我们刚刚编写好的SqlDataAccess,cs抽象提取出了一个ISqlDataAccess.cs的抽象类。内容具体如下:
在这里插入图片描述

点击我们想要抽象提取的类,在其内容中右键其class类名。

namespace DataAccess.DbAccess;

public interface ISqlDataAccess
{
    Task<IEnumerable<T>> LoadData<T, U>(string storedProcedure, U parameters, string connectionId = "Default");
    Task SaveData<T>(string storedProcedure, T parameters, string connectionId = "Default");
}
抽象类中只用之前类中的两个方法的定义,但是我们现在就**可以在任何地方去引用他们**,这样的话就可以轻松的使用我们的**依赖注入**。

​ 执行了抽象命令之后, 我们再查看SqlDataAccess.cs就可以看到现在已经实现了抽象类ISqlDataAccess.cs
在这里插入图片描述

创建用户数据类

UserData.cs

​ 在我的API项目中我们是通过SQL语句去同数据进行交谈的,而不是我们直接同数据文件进行交谈,因此UserData就是我们与之交谈以获取用户数据的地方。

快捷方式:通过变量来创建与之对应的类的有参构造函数
在这里插入图片描述

代码分析:

public Task<IEnumerable<UserModel>> GetUsers() =>
        _db.LoadData<UserModel, dynamic>("dbo.spUser_GetAll", new { });

dynamic:可以传入任何类型的参数,在这里的意思就是没有(LoadData函数的定义中的第二个泛型为参数信息,而我们这里是查询所有人的信息 故不需要),因此对应的方法后面的参数填的是new { }(意思是我们没有参数,但是我们必须传递一些东西),所以这里也就体现了dynamic中的可传入任何类型的特征(包括了为空)

    public async Task<IEnumerable<T>> LoadData<T, U>(
        string storedProcedure, /*存储过程*/
        U parameters,
        string connectionId = "Default")
    {
        using IDbConnection connection = new SqlConnection(_config.GetConnectionString(connectionId));

        return await connection.QueryAsync<T>(storedProcedure, parameters,
            commandType: CommandType.StoredProcedure);
    }

注意:

​ 上面的一行的GetUsers()是一个完整的方法,之所以这里没有花括号是因为它的方法体只有一行,它只需要一个分号就可以了(使用=>,但是不是Lambda )

​ public Task<IEnumerable> GetUsers() 方法体中的泛型现在指定为UserModel,其实就是我们LoadData()方法中有关于泛型参数的类型后指定


public async Task<UserModel?> GetUser(int id)
{
        var results = await _db.LoadData<UserModel, dynamic>(
            "dbo.spUser_Get",
            new { Id = id });   /*是因为我们传入的id参数写法不一样,使用该用法来完成一个复制操作*/
        return results.FirstOrDefault(); 
}

分析

UserModel**?** :表示UserModel可以为空

results.FirstOrDefault(); 返回我们**无数的第一条记录(因为得到的results是一个集合,而我们返回的只有一条)或者返回默认值**(对于我们的用户模型而已就是空的)

part2

​ 我们正在构建一个完整的应用程序,其中包含一个sql数据库、一个使用dapper的数据访问层和一个最小的API前端

连接字符串

​ 通过查看localDB属性,我们就可以找到connection string(连接字符串),而在appsettings.json中是可以设置连接字符串。
在这里插入图片描述
在这里插入图片描述

目前的项目目录

目前的项目目录结构图如下:
在这里插入图片描述

SqlDataAccess.cs:使用dapper与我们的SQL数据库对话的地方

UserData.cs:调用ISqlDataAccess.cs中的方法(实际是SqlDataAccess.cs中定义的方法)来操纵与user相关的数据及其操作

对应的IUserData.cs和ISqlDataAccess.cs是对应页面生成的抽象接口类(interface)

UserDB下是与数据处理和存储相关的类。dbo文件下storedprocedures是存储过程、table数据表、script.postdeployment.sql是一个后期部署脚本,将其发布得到UserDB.publish.xml,UserDB.publish.xml运行就可以进行后期部署脚本中关于数据更新的集合操作。

项目的主题部分

接下来我们就只注意项目的主题部分即为
在这里插入图片描述

①在appsettings.json中设置连接字符串,具体参考上面的连接字符串。结果如下:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  //ASP.NET Core [配置]系统会**读取 键**。 进行本地开发时,配置从 `appsettings.json` 文件**获取连接字符串**。生成的连接字符串类似于以下 JSON
  "ConnectionStrings": {
    "Default": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=MinimalAPIUserDB;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
  }

​ 我们在SqlDataAccess.cs中定义数据处理方法中提到的connectionId都是设置的为默认值Default,其实就是我们这里设置的值,即为连接本地的SQL数据库《键对值》。
在这里插入图片描述

完成了连接字符串的设置之后,我们就可以同数据库进行对话了。

Program.cs

​ 包含在运行时管理 Web 应用的配置文件。 默认应用程序配置存储在 appsettings.json。 但是,可使用 appsettings.Development.json 替代这些设置 。 展开 appsettings.json 文件以查看 appsettings.Development.json 文件.

​ 我们现在看的的Program.cs中的内容是.net6中的规范,是之前Program.cs和startup.cs整合的结果。

在这个文件中你看不到using、方法体等,它的的本质就是一个**启动文件,这里的所有内容都在一个隐藏的静态void main** ,实际上它是一个静态异步main任务.所以我们可以在这里执行异步任务,但是他们都是隐藏的。

代码讲解

//会创建一个带有预配置默认值的 `WebApplicationBuilder`,向[依赖项注入(DI) 容器]添加 页面支持,并生成应用(配置web应用程序)
var builder = WebApplication.CreateBuilder(args); //带有预配置默认值

//依赖注入
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

//生成应用
var app = builder.Build();
//之后我们就可以访问应用程序相关的配置信息了

开发人员异常页默认启用,并提供有关异常的有用信息。 生产应用不得在开发模式中运行,原因是开发人员异常页可能会泄露敏感信息。

razor pages 中的相关设置的额外内容

—>下面的代码会将异常终结点设置为 /Error,并且当应用未在开发模式中运行时,启用 HTTP 严格传输安全协议 (HSTS)

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())  //应用未在开发模式中运行时
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

​ 例如,当应用在生产或测试模式中时,会运行前面的代码。 有关详细信息,请参阅在 ASP.NET Core 中使用多个环境

下列代码会启用各种中间件

  • app.UseHttpsRedirection();:将 HTTP 请求重定向到 HTTPS。
  • app.UseStaticFiles();:使能够提供 HTML、CSS、映像和 JavaScript 等静态文件。 有关详细信息,请参阅 ASP.NET Core 中的静态文件
  • app.UseRouting();:向中间件管道添加路由匹配。 有关详细信息,请参阅 ASP.NET Core 中的路由
  • app.MapRazorPages();:为 Razor Pages 配置终结点路由。
  • app.UseAuthorization();:授权用户访问安全资源。 此应用不使用授权,因此可删除此行。
  • app.Run();:运行应用。

运行程序生成如下页面:
在这里插入图片描述

.net6中端口号在7000左右

app.UseHttpsRedirection(); 
//将 HTTP 请求重定向到 HTTPS(这就意味着我们不允许用户使用http来访问我们的网站,如果一定要这么做的话就进行重定向我们想要的https版本)。

除掉program.cs中的原始方法

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
       new WeatherForecast
       (
           DateTime.Now.AddDays(index),
           Random.Shared.Next(-20, 55),
           summaries[Random.Shared.Next(summaries.Length)]
       ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast");


internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

​ 删除完之后,我们就没有任何东西可以在我们项目中运行。现在我们开始添加东西,我们将要添加的第一件事就是**依赖项**。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4vU7RUC1-1666606879549)(C:\Users\23972\AppData\Roaming\Typora\typora-user-images\image-20221012205552184.png)]

右键“依赖项”,选择“添加项目引用”。选择dataaccess.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DkqjwejA-1666606879550)(D:\实践+学习\Web\photo\image-20221012205730191.png)]

​ 现在我们就可以与dataaccess进行访问了。为了实现它我们在program.cs进行相关配置

builder.Services.AddSingleton<ISqlDataAccess, SqlDataAccess>();
builder.Services.AddSingleton<IUserData, UserData>();

AddSingleton(IServiceCollection, Type, Func<IServiceProvider,Object>)方法
这个方法是通过提供一个Func<IServiceProvider,Object>的delegate委托来实现服务的实例获取。具体怎么用,下面给一个简单例子:
———————————————
这个重载便于我们利用已经存在服务容器中的服务来生成需要取得的服务对象

​ 就像这样,它将向我们的依赖注入系统添加两件事,ISqlDataAccess和IUserData。我们知道我们是使用UserData同数据库进行数据对话,但是我们需要在我们的依赖注入系统中拥有它来进行数据访问。它需要注入我们的项目配置中去,并且UserData也需要知道它的存在,因为它使用了ISqlDataAccess。

现在这两个属性就在我们的数据访问系统中了。

设置全局变量

首先,我们不得不在任何地方都使用DataAccess.DbAccess。 所以我们可以直接在program.cs中设置如下:

①使用global

global using DataAccess.DbAccess;

②使用”startup“文件来统一管理

​ 但是为了项目的统一管理,我们并不采取这种做法。因为只有我们后期在项目中新填内容会导致program.cs变得紧凑起来,为了避免这个局面。我们就用回之前.net版本中的startup,去创建一个类来实现类似的功能。

在项目下新建一个GlobalUsings.cs

除掉新建文件中初始的内容

将之前的global using DataAccess.DbAccess;从program,cs中移到GlobalUsings.cs中,那么现在我们就可以在项目的任何地方去使用DataAccess.DbAccess,而不是只能在program,cs中使用。

global using DataAccess.Data;
global using DataAccess.Models;

API配置

​ 接下俩我们开始进行**API(应用程序编程接口)的配置,我们可以让所有的事情都交给program.cs来完成**,这是一种方法。但是我们这里同样是采用一个类来单独进行管理。

通过这种方式的话,我们在program.cs中就并没有在做工作, 它只是在告诉别人要做什么工作。(它是一个管理者而不是一个执行者)

在项目下新建一个Api.cs

在这个文件里面我们可以完成一些很简单的任务 同时我们也可以完成一些很复杂的东西。那么到了那个时候我们就只要controller而不是这里的API了。而这里我们只是想完成与一个最小的API,所以在这里我们就只有一个名为public class API的类。并可以在program.cs中对他进行引用

进行相关的API功能创建:

private static async Task<IResult> GetUsers(IUserData data)
{
        try
        {
            return Results.Ok(await data.GetUsers());
        }
        catch (Exception ex)
        {
            return Results.Problem(ex.Message);
        }
}
这里的这个方法实际上是**要向依赖注入系统询问IUserData**,而我们的IUserData中就是由UserData中得到的五种方法。那么我们这里的GetUsers方法就可以获取到 IUserData中的所有方法。

​ 其实这里的实际语句就只有一行:await data.GetUsers()。但是为了程序的容错性,我们将其加入到了这里的一个try catch中。

​ 方法写完了之后,我们就进行**端口映射**。

public static void ConfigureApi(this WebApplication app)
    {
        // All of my API endpoint mapping
        app.MapGet("/Users", GetUsers);
    }
app.MapGet("/", () => "Hello .NET Mini API!"); 

​ Mini API一大好处是简单明了,拿来就用,比如上面的这行代码,MapGet的参数有两个,第一个是路由信息,第二个实现方法,总体意思就是“这个通道做什么”(这个通道是第一个参数,做什么第二个参数),在这里,第二个参数其实是Lambda表达式,也可以换成一个方法(函数),这个方法是是静态方法也好,实例方法也罢,主要是能完成干什么就可以。

​ 该方法在此处执行此调用,它与我们的数据库对话,这是与我们数据库的全部。但是我们要明确的一点就是这里没有SQL知识,我们也并不知道在哪里与SQL进行交谈,我只知道我需要users ,我将在这里等待这些用户的结果,如果返回成功我们就返回OK;如果返回失败我们将抛出一个问题,或者我们将返回带有该错误消息。

ConfigureApi(this WebApplication app): 参数设置为WebApplication 的原因如下

​ 在API.cs中我们所定义的端口方法都是private的,这就意味着在这个静态公开类API(public static)中唯一公开的东西就是这里的 public static void ConfigureApi(this WebApplication app)。及时我们现在正在使用这些私有方法并将其映射到了我们的端点上。这也就是为什么在外面program.cs中我们只能访问到app.ConfigureApi();

​ 其实说白了就是,我们想利用API.CS中的私有方法,但是外界是拿不到的。这个时候我们利用外界可以拿到的其中的ConfigureApi,在其里面做一个端口映射。那么我们就可以利用访问这个可访问的ConfigureApi()去进一步去访问原先不可访问的API.CS中的私有方法。


第二个API端口设置

private static async Task<IResult> GetUser(int id, IUserData data)
    {
        try
        {
            var results = await data.GetUser(id);
            if (results == null) return Results.NotFound();
            return Results.Ok(results);
        }
        catch (Exception ex)
        {
            return Results.Problem(ex.Message);
        }
    }

​ 在这种情况下,我们要求提供两条不同信息。IUserData 来自于依赖注入,id来自于用户(来自于core对api的调用)

​ 方法写完了之后,我们就进行**端口映射**。

public static void ConfigureApi(this WebApplication app)
    {
        app.MapGet("/Users/{id}", GetUser);
    }

第三个API端口设置

private static async Task<IResult> InsertUser(UserModel user, IUserData data)
    {
        try
        {
            await data.InsertUser(user);
            return Results.Ok();
        }
        catch (Exception ex)
        {
            return Results.Problem(ex.Message);
        }
    }

​ 这里的UserModel user是可以直接拿到的,因为它是来自于GlobalUsings.cs,所以我们知道它在哪里。

​ 方法写完了之后,我们就进行**端口映射**。

public static void ConfigureApi(this WebApplication app) /*WebApplication:使得外界可以通过这里的端口映射方法访问其类中的私有方法*/
    {
        app.MapPost("/Users", InsertUser);
    }

第四个API端口设置

private static async Task<IResult> UpdateUser(UserModel user, IUserData data)
    {
        try
        {
            await data.UpdateUser(user);
            return Results.Ok();
        }
        catch (Exception ex)
        {
            return Results.Problem(ex.Message);
        }
    }

同理如上一个。

方法写完了之后,我们就进行**端口映射**。

public static void ConfigureApi(this WebApplication app) /*WebApplication:使得外界可以通过这里的端口映射方法访问其类中的私有方法*/
    {
        app.MapPut("/Users", UpdateUser);
    }

第五个API端口设置

private static async Task<IResult> DeleteUser(int id, IUserData data)
    {
        try
        {
            await data.DeleteUser(id);
            return Results.Ok();
        }
        catch (Exception ex)
        {
            return Results.Problem(ex.Message);
        }
    }

同理第二个端口设置。

方法写完了之后,我们就进行**端口映射**。

public static void ConfigureApi(this WebApplication app) /*WebApplication:使得外界可以通过这里的端口映射方法访问其类中的私有方法*/
    {
        app.MapDelete("/Users/{id}", DeleteUser);
    }

在**方法传参上注意一点就是。我们从用户那里获得的完整的UserModel**,所以这个UserModel是来自于我们的user用户的。而我们通过命令行或者命令URL中传入id等参数时,这适用于get但我们不想为其他事情也这样做比如更新或者插入更新,所以我们将通过主题传递它.它任然在相同的参数列表,系统也任然可以理解它并正确处理这些信息。

private static async Task<IResult> DeleteUser(int id, IUserData data)
和
private static async Task<IResult> UpdateUser(UserModel user, IUserData data)

建议:

​ 您正在执行任何类型的真正编码,那么在API.CS尝试部分中的工作可能比两行或三行代码更多,建议我们在它放在我们自己的业务逻辑部分,而不是在这里的API.CS中。

微服务:

​ 我们需要做一些工作,而这个已经超过了azure函数所能做的事情。在这种情况下,您必须拥有多个端点,在这种情况下你可以创建一个最小的API,而这些事情的方法我们只需要几行代码就可以搞定。在API.CS中我们设置了一些解决问题的方法,而这里就是我们API最大部分。

​ 由于我们对数据库具有完整的crud访问权限,如果只有一个表,我们一个label就可以搞定,如果有多个表的话,但是此时已经超出了微服务正在做的事情,所以着对于微服务来说是很有帮助的,因为在这里我们不需要做很多的设置内容,我们可以将其模块化,甚至我们都可以不用去更改program.cs,只需要在API.CS中的ConfigureApi函数中做对应的修改(新填映射的话就需要增加其对应的映射函数)以及其调用的方法。

​ 因此即使这是一个很小的API,但是他也是正确开始的地方,从这个基础上,我们可以从端点开始考虑,并确定是否需要扩展。现在我们使用的控制器在很多情况下是不需要扩展的,如果我们需要的话,那么我们绝对可以在我们的API或者直接在这里的api.cs中操作。

总的一点就是 尽量把所有的事情都交给类库来处理,这样的话我们就可以让页面尽量的精简,并且也方便后面类库功能的替换和修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值