亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用MediatR實現POST請求

發布時間:2021-12-27 16:55:48 來源:億速云 閱讀:221 作者:iii 欄目:開發技術

本篇內容介紹了“如何使用MediatR實現POST請求”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

    需求

    需求很簡單:如何創建新的TodoList和TodoItem并持久化。

    初學者按照教程去實現的話,應該分成以下幾步:創建Controller并實現POST方法;實用傳入的請求參數new一個數據庫實體對象;調用IRepository<T>完成數據庫的寫入,最多會在中間加一層Service。這個做法本身沒有問題,也是需要從初學階段開始扎實地掌握開發技能的必經之路,有助于幫助理解邏輯調用的過程。

    對于稍微正式一些的項目,.NET工程上習慣的實現是通過使用一些比較成熟的類庫框架,有效地對業務邏輯進行分類管理、消除冗余代碼,以達到業務邏輯職責清晰簡潔的目的。在這個階段我們經常使用的兩個類庫分別是AutoMapper和MediatR。

    目標

    合理組織并使用MediatR,完成POST請求。

    原理與思路

    首先來簡單地介紹一下這個類庫。

    關于CQRS模式、中介者模式和MediatR

    CQRS模式

    CQRS模式全稱是“Command Query Responsibility Segregation”,正如字面意思,CQRS模式的目的在于將讀取操作和寫入操作的指責區分開,并使用不同的Model去表示。從CRUD的角度來說,就是把R和CUD區分開來對待。如下圖所示:

    如何使用MediatR實現POST請求

    這個模式可以有效地應用到具有主從分離的數據庫架構中,當需要獲取數據時,從只讀數據庫(一般是從庫)中讀取數據,當需要寫入或更新數據時,向主庫進行操作。

    CQRS模式旨在解決的問題是:為了屏蔽數據庫層面“寫優先”還是“讀優先”的優化設計策略,在業務邏輯側進行解耦。

    任何設計模式都是對解決特定問題的一個Trade off,自然也帶來了一些缺點,首先就是服務內部的組件復雜度上升了,因為需要創建額外的類來實現CQRS模式;其次如果數據層是分離的,那么可能會有數據的狀態不一致問題。

    中介者Mediator模式

    這是23種基本設計模式中的一個,屬于行為型設計模式,它給出了組件之間交互的一種解耦的方式。簡單參考下圖,具體內容就不過多解釋了,任何一篇介紹設計模式的文章都有介紹。

    如何使用MediatR實現POST請求

    這種設計模式實際上是一種采用依賴倒置(Inversion of Control, IoC)的方式,實現了圖中藍色組件的松耦合。

    MediatR

    這是在開發中被廣泛采用的實現以上兩種設計模式的類庫,更準確的說法是,它通過應用中介者模式,實現了進程內CQRS。基本思想是所有來自API接口和數據存儲之間的邏輯,都需要通過MediatR來組織(即所謂的“中介者”)。

    從實現上看,MediatR提供了幾組用于不同場景的接口,我們在本文中處理的比較多的是IRequest<T>/IRequestHandler<T>以及INotification<T>/INotificationHander<T>兩組接口,更多的請參考官方文檔和例子。

    實現

    所有需要使用MediatR的地方都集中在Application項目中。

    引入MediatR

    $ dotnet add src/TodoList.Application/TodoList.Application.csproj package MediatR.Extensions.Microsoft.DependencyInjection

    為了適配CQRS的模式,我們在Application項目中的TodoLists和TodoItems下相同地創建幾個文件夾:

    Commands:用于組織CUD相關的業務邏輯;

    Queries:用于組織R相關的業務邏輯;

    EventHandlers:用于組織領域事件處理的相關業務邏輯。

    在Application根目錄下同樣創建DependencyInjection.cs用于該項目的依賴注入:

    DependencyInjection.cs

    using System.Reflection;
    
    using Microsoft.Extensions.DependencyInjection;
    
    
    
    namespace TodoList.Application;
    
    
    
    public static class DependencyInjection
    
    {
    
        public static IServiceCollection AddApplication(this IServiceCollection services)
    
        {
    
            services.AddMediatR(Assembly.GetExecutingAssembly());
    
            return services;
    
        }
    
    }

    并在Api項目中使用:

    // 省略其他...
    // 添加應用層配置
    builder.Services.AddApplication();
    // 添加基礎設施配置
    builder.Services.AddInfrastructure(builder.Configuration);

    實現Post請求

    在本章中我們只實現TodoList和TodoItem的Create接口(POST),剩下的接口后面的文章中逐步涉及。

    POST TodoList

    在Application/TodoLists/Commands/下新建一個目錄CreateTodoList用于存放創建一個TodoList相關的所有邏輯:

    CreateTodoListCommand.cs

    using MediatR;
    
    using TodoList.Application.Common.Interfaces;
    
    
    
    namespace TodoList.Application.TodoLists.Commands.CreateTodoList;
    
    
    
    public class CreateTodoListCommand : IRequest<Guid>
    
    {
    
        public string? Title { get; set; }
    
    }
    
    
    
    public class CreateTodoListCommandHandler : IRequestHandler<CreateTodoListCommand, Guid>
    
    {
    
        private readonly IRepository<Domain.Entities.TodoList> _repository;
    
    
    
        public CreateTodoListCommandHandler(IRepository<Domain.Entities.TodoList> repository)
    
        {
    
            _repository = repository;
    
        }
    
    
    
        public async Task<Guid> Handle(CreateTodoListCommand request, CancellationToken cancellationToken)
    
        {
    
            var entity = new Domain.Entities.TodoList
    
            {
    
                Title = request.Title
    
            };
    
    
    
            await _repository.AddAsync(entity, cancellationToken);
    
            return entity.Id;
    
        }
    
    }

    有一些實踐是將Request和RequestHandler分開兩個文件,我更傾向于像這樣將他倆放在一起,一是保持簡潔,二是當你需要順著一個Command去尋找它對應的Handler時,不需要更多的跳轉。

    接下來在TodoListController里實現對應的POST方法,

    using MediatR;
    
    using Microsoft.AspNetCore.Mvc;
    
    using TodoList.Application.TodoLists.Commands.CreateTodoList;
    
    
    
    namespace TodoList.Api.Controllers;
    
    
    
    [ApiController]
    
    [Route("/todo-list")]
    
    public class TodoListController : ControllerBase
    
    {
    
        private readonly IMediator _mediator;
    
    
    
        // 注入MediatR
    
        public TodoListController(IMediator mediator)
    
            => _mediator = mediator;
    
    
    
        [HttpPost]
    
        public async Task<Guid> Create([FromBody] CreateTodoListCommand command)
    
        {
    
            var createdTodoList = await _mediator.Send(command);
    
    
    
            // 出于演示的目的,這里只返回創建出來的TodoList的Id,
    
            // 實際使用中可能會選擇IActionResult作為返回的類型并返回CreatedAtRoute對象,
    
            // 因為我們還沒有去寫GET方法,返回CreatedAtRoute會報錯(找不到對應的Route),等講完GET后會在那里更新
    
            return createdTodoList.Id;
    
        }
    
    }

    POST TodoItem

    類似TodoListController和CreateTodoListCommand的實現,這里我直接把代碼貼出來了。

    CreateTodoItemCommand.cs

    using MediatR;
    
    using TodoList.Application.Common.Interfaces;
    
    using TodoList.Domain.Entities;
    
    using TodoList.Domain.Events;
    
    
    
    namespace TodoList.Application.TodoItems.Commands.CreateTodoItem;
    
    
    
    public class CreateTodoItemCommand : IRequest<Guid>
    
    {
    
        public Guid ListId { get; set; }
    
    
    
        public string? Title { get; set; }
    
    }
    
    
    
    public class CreateTodoItemCommandHandler : IRequestHandler<CreateTodoItemCommand, Guid>
    
    {
    
        private readonly IRepository<TodoItem> _repository;
    
    
    
        public CreateTodoItemCommandHandler(IRepository<TodoItem> repository)
    
        {
    
            _repository = repository;
    
        }
    
    
    
        public async Task<Guid> Handle(CreateTodoItemCommand request, CancellationToken cancellationToken)
    
        {
    
            var entity = new TodoItem
    
            {
    
                // 這個ListId在前文中的代碼里漏掉了,需要添加到Domain.Entities.TodoItem實體上
    
                ListId = request.ListId,
    
                Title = request.Title,
    
                Done = false
    
            };
    
    
    
            await _repository.AddAsync(entity, cancellationToken);
    
    
    
            return entity.Id;
    
        }
    
    }

    TodoItemController.cs

    using MediatR;
    
    using Microsoft.AspNetCore.Mvc;
    
    using TodoList.Application.TodoItems.Commands.CreateTodoItem;
    
    
    
    namespace TodoList.Api.Controllers;
    
    
    
    [ApiController]
    
    [Route("/todo-item")]
    
    public class TodoItemController : ControllerBase
    
    {
    
        private readonly IMediator _mediator;
    
    
    
        // 注入MediatR
    
        public TodoItemController(IMediator mediator) 
    
            => _mediator = mediator;
    
    
    
        [HttpPost]
    
        public async Task<Guid> Create([FromBody] CreateTodoItemCommand command)
    
        {
    
            var createdTodoItem = await _mediator.Send(command);
    
    
    
            // 處于演示的目的,這里只返回創建出來的TodoItem的Id,理由同前
    
            return createdTodoItem.Id;
    
        }
    
    }

    驗證

    運行Api項目,通過Hoppscotch發送對應接口請求:

    創建TodoList驗證

    請求

    如何使用MediatR實現POST請求

    返回

    如何使用MediatR實現POST請求

    數據庫

    如何使用MediatR實現POST請求

    第一條數據是種子數據,第二條是我們剛才創建的。

    創建TodoItem驗證

    繼續拿剛才創建的這個TodoList的Id來創建新的TodoItem:

    請求

    如何使用MediatR實現POST請求

    返回

    如何使用MediatR實現POST請求

    數據庫

    如何使用MediatR實現POST請求

    最后一條是我們新創建的,其余是種子數據。

    “如何使用MediatR實現POST請求”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    双鸭山市| 巴林右旗| 封开县| 漠河县| 陆河县| 普安县| 札达县| 景洪市| 炉霍县| 汝州市| 泸定县| 永嘉县| 溧阳市| 雷山县| 德惠市| 江陵县| 富源县| 铅山县| 冕宁县| 博湖县| 中阳县| 靖宇县| 临清市| 张家港市| 绥江县| 兴仁县| 乌苏市| 乌恰县| 沙河市| 浪卡子县| 玉门市| 拉孜县| 十堰市| 乌兰察布市| 根河市| 舟曲县| 西藏| 平原县| 航空| 大新县| 连山|