怪物奇妙物语

宇宙无敌超级美少男的怪物奇妙物语

首页 新随笔 联系 管理
  822 随笔 :: 0 文章 :: 2 评论 :: 16万 阅读

MediatR CQRS

最重要的两个接口:
IRequest
IRequestHandler

public class GetMoviesQuery : IRequest<IList<GetMovieDto>> { }
public class GetMoviesQueryHandler : IRequestHandler<GetMoviesQuery, IList<GetMovieDto>>{
public async Task<IList<GetMovieDto>> Handle()
}

程序整体架构图

基础设施层
领域层
应用层
控制层
客户端
领域实体
ApplicationDbContext
数据库上下文
SQL Server
数据库
数据传输对象
CreateMovieDto
GetMovieDto
枚举
MovieGenre
电影类型
Movie
电影实体
MediatR
中介者模式
CreateMovieCommand
创建电影命令
GetMoviesQuery
获取电影列表查询
GetMovieQuery
根据ID获取电影查询
CreateUserCommandHandler
创建电影处理器
GetMoviesQueryHandler
获取电影列表处理器
GetMovieQueryHandler
根据ID获取电影处理器
MovieController
处理HTTP请求
HTTP请求

程序流程图

MovieApplicationDbContextGetMovieQueryHandlerCreateUserCommandHandlerMediatRMovieControllerClientMovieApplicationDbContextGetMovieQueryHandlerCreateUserCommandHandlerMediatRMovieControllerClientPOST /api/movie (CreateMovieRequest)Send(CreateMovieCommand)Handle(CreateMovieCommand)CreateMovie()AddAsync(Movie), SaveChangesAsync()CreateMovieDtoCreateMovieDtoHTTP 200 OK (CreateMovieDto)GET /getmovies/{id}Send(GetMovieQuery)Handle(GetMovieQuery)FindByIdAsync(id)MovieMapTo() as GetMovieDtoGetMovieDtoGetMovieDtoHTTP 200 OK (GetMovieDto)

CQRS-and-MediatR-demo-master\MediatR_Demo\appsettings.Development.json

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\appsettings.json

{
"ConnectionStrings": {
"Standard": "Server=localhost;Database=mediatr-demo;Trusted_Connection=True;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

CQRS-and-MediatR-demo-master\MediatR_Demo\MediatR_Demo.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MediatR" Version="10.0.1" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>
</Project>

CQRS-and-MediatR-demo-master\MediatR_Demo\Program.cs

using MediatR;
using MediatR_Demo.Repository.Context;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("Standard"))
);
builder.Services.AddMediatR(typeof(Program));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

CQRS-and-MediatR-demo-master\MediatR_Demo\Application\Movies\Commands\CreateMovie\CreateMovieCommand.cs

using MediatR;
using MediatR_Demo.Core.Enums;
using MediatR_Demo.Domain.DTOs.Responses.Movie;
namespace MediatR_Demo.Application.Movies.Commands.CreateMovie;
public class CreateMovieCommand : IRequest<CreateMovieDto>
{
public CreateMovieCommand(string? title, string? description, MovieGenre? genre, int? rating)
{
Title = title;
Description = description;
Genre = genre;
Rating = rating;
}
public string? Title { get; set; }
public string? Description { get; set; }
public MovieGenre? Genre { get; set; }
public int? Rating { get; set; }
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Application\Movies\Commands\CreateMovie\CreateUserCommandExtension.cs

using MediatR_Demo.Domain.Entities.Movie;
namespace MediatR_Demo.Application.Movies.Commands.CreateMovie
{
public static class CreateUserCommandExtension
{
public static Movie CreateMovie(this CreateMovieCommand command)
{
var movie = new Movie
(
command.Title,
command.Description,
command.Genre,
command.Rating
);
return movie;
}
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Application\Movies\Commands\CreateMovie\CreateUserCommandHandler.cs

using MediatR;
using MediatR_Demo.Domain.DTOs.Responses.Movie;
using MediatR_Demo.Repository.Context;
namespace MediatR_Demo.Application.Movies.Commands.CreateMovie
{
public class CreateUserCommandHandler : IRequestHandler<CreateMovieCommand, CreateMovieDto>
{
private readonly ApplicationDbContext _dbContext;
public CreateUserCommandHandler(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<CreateMovieDto> Handle(CreateMovieCommand request, CancellationToken cancellationToken)
{
Domain.Entities.Movie.Movie movie = request.CreateMovie();
await _dbContext.Movies.AddAsync(movie);
await _dbContext.SaveChangesAsync();
return new CreateMovieDto(movie.Id);
}
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Application\Movies\Queries\GetMovie\GetMovieQuery.cs

using MediatR;
using MediatR_Demo.Domain.DTOs.Responses.Movie;
namespace MediatR_Demo.Application.Movies.Queries.GetMovie;
public class GetMovieQuery : IRequest<GetMovieDto>
{
public long? Id { get; set; }
public GetMovieQuery(long? id)
{
Id = id;
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Application\Movies\Queries\GetMovie\GetMovieQueryExtensions.cs

using MediatR_Demo.Domain.DTOs.Responses.Movie;
using MediatR_Demo.Domain.Entities.Movie;
namespace MediatR_Demo.Application.Movies.Queries.GetMovie;
public static class GetMovieQueryExtensions
{
public static GetMovieDto MapTo(this Movie movie)
{
return new GetMovieDto
{
Id = movie.Id,
Title = movie.Title,
Description = movie.Description,
Genre = movie.Genre,
Rating = movie.Rating
};
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Application\Movies\Queries\GetMovie\GetMovieQueryHandler.cs

using MediatR;
using MediatR_Demo.Domain.DTOs.Responses.Movie;
using MediatR_Demo.Repository.Context;
using Microsoft.EntityFrameworkCore;
namespace MediatR_Demo.Application.Movies.Queries.GetMovie;
public class GetMovieQueryHandler : IRequestHandler<GetMovieQuery, GetMovieDto>
{
private readonly ApplicationDbContext _dbContext;
public GetMovieQueryHandler(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<GetMovieDto> Handle(
GetMovieQuery request,
CancellationToken cancellationToken
)
{
var movie = await _dbContext.Movies.Where(x => x.Id == request.Id).FirstOrDefaultAsync();
if (movie != null)
{
var movieItem = movie.MapTo();
return movieItem;
}
return null;
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Application\Movies\Queries\GetMovies\GetMoviesQuery.cs

using MediatR;
using MediatR_Demo.Domain.DTOs.Responses.Movie;
namespace MediatR_Demo.Application.Movies.Queries.GetMovies;
public class GetMoviesQuery : IRequest<IList<GetMovieDto>> { }

CQRS-and-MediatR-demo-master\MediatR_Demo\Application\Movies\Queries\GetMovies\GetMoviesQueryExtensions.cs

using MediatR_Demo.Domain.DTOs.Responses.Movie;
using MediatR_Demo.Domain.Entities.Movie;
namespace MediatR_Demo.Application.Movies.Queries.GetMovies;
public static class GetMoviesQueryExtensions
{
public static GetMovieDto MapTo(this Movie movie)
{
return new GetMovieDto
{
Id = movie.Id,
Title = movie.Title,
Description = movie.Description,
Genre = movie.Genre,
Rating = movie.Rating
};
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Application\Movies\Queries\GetMovies\GetMoviesQueryHandler.cs

using MediatR;
using MediatR_Demo.Domain.DTOs.Responses.Movie;
using MediatR_Demo.Repository.Context;
using Microsoft.EntityFrameworkCore;
namespace MediatR_Demo.Application.Movies.Queries.GetMovies;
public class GetMoviesQueryHandler : IRequestHandler<GetMoviesQuery, IList<GetMovieDto>>
{
private readonly ApplicationDbContext _dbContext;
public GetMoviesQueryHandler(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<IList<GetMovieDto>> Handle(
GetMoviesQuery request,
CancellationToken cancellationToken
)
{
var movies = await _dbContext.Movies.ToListAsync();
var movieList = new List<GetMovieDto>();
foreach (var movieItem in movies)
{
var movie = movieItem.MapTo();
movieList.Add(movie);
}
return movieList;
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Controllers\MovieController.cs

using MediatR;
using MediatR_Demo.Application.Movies.Commands.CreateMovie;
using MediatR_Demo.Application.Movies.Queries.GetMovie;
using MediatR_Demo.Application.Movies.Queries.GetMovies;
using MediatR_Demo.Domain.DTOs.Requests.Movie;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace MediatR_Demo.Controllers;
[Route("api/[controller]")]
[ApiController]
public class MovieController : ControllerBase
{
private readonly IMediator _mediator;
public MovieController(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet]
public async Task<IActionResult> GetMovies()
{
var movies = await _mediator.Send(new GetMoviesQuery());
if (movies != null)
{
return Ok(movies);
}
return NotFound("No movies in database. Please add a movie first.");
}
[HttpGet("/getmovies/{id}")]
public async Task<IActionResult> GetMovie(long id)
{
var movie = await _mediator.Send(new GetMovieQuery(id));
if (movie != null)
{
return Ok(movie);
}
return NotFound($"No movie in database with ID: {id}.");
}
[HttpPost]
public async Task<IActionResult> CreateMovie([FromBody] CreateMovieRequest request)
{
var movie = await _mediator.Send(
new CreateMovieCommand(
request.Title,
request.Description,
request.Genre,
request.Rating
)
);
return Ok(movie);
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Core\Enums\MovieGenre.cs

namespace MediatR_Demo.Core.Enums;
public enum MovieGenre
{
Action,
Comedy,
Drama,
Fantasy,
Horror,
Mystery,
Romance,
Thriller,
Western
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Domain\DTOs\Requests\Movie\CreateMovieRequest.cs

using MediatR_Demo.Core.Enums;
namespace MediatR_Demo.Domain.DTOs.Requests.Movie
{
public class CreateMovieRequest
{
public string? Title { get; set; }
public string? Description { get; set; }
public MovieGenre? Genre { get; set; }
public int? Rating { get; set; }
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Domain\DTOs\Responses\Movie\CreateMovieDto.cs

namespace MediatR_Demo.Domain.DTOs.Responses.Movie
{
public class CreateMovieDto
{
public CreateMovieDto(long id)
{
Id = id;
}
public long Id { get; set; }
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Domain\DTOs\Responses\Movie\GetMovieDto.cs

using MediatR_Demo.Core.Enums;
namespace MediatR_Demo.Domain.DTOs.Responses.Movie
{
public class GetMovieDto
{
public long Id { get; set; }
public string? Title { get; set; }
public string? Description { get; set; }
public MovieGenre? Genre { get; set; }
public int? Rating { get; set; }
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Domain\Entities\Movie\Movie.cs

using MediatR_Demo.Core.Enums;
namespace MediatR_Demo.Domain.Entities.Movie
{
public class Movie
{
public Movie(string? title, string? description, MovieGenre? genre, int? rating)
{
Title = title;
Description = description;
Genre = genre;
Rating = rating;
}
public long Id { get; set; }
public string? Title { get; set; }
public string? Description { get; set; }
public MovieGenre? Genre { get; set; }
public int? Rating { get; set; }
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Properties\launchSettings.json

{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:14989",
"sslPort": 44321
}
},
"profiles": {
"MediatR_Demo": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7001;http://localhost:7000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo\Repository\Context\ApplicationDbContext.cs

using MediatR_Demo.Domain.Entities.Movie;
using Microsoft.EntityFrameworkCore;
namespace MediatR_Demo.Repository.Context
{
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options) { }
public DbSet<Movie> Movies { get; set; }
}
}

CQRS-and-MediatR-demo-master\MediatR_Demo.sln

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediatR_Demo", "MediatR_Demo\MediatR_Demo.csproj", "{40AF7C5A-7DFD-452F-BB6F-47E42F59F27D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{40AF7C5A-7DFD-452F-BB6F-47E42F59F27D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{40AF7C5A-7DFD-452F-BB6F-47E42F59F27D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{40AF7C5A-7DFD-452F-BB6F-47E42F59F27D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40AF7C5A-7DFD-452F-BB6F-47E42F59F27D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {932BD9F0-738E-40A5-8E0B-276918C9FF07}
EndGlobalSection
EndGlobal
posted on   超级无敌美少男战士  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2023-02-28 sqlalchemy 原生sql查询 返回字典形式数据
2023-02-28 python list array 复制 区别 浅拷贝 深拷贝
2022-02-28 cs_css实现两栏三栏布局
点击右上角即可分享
微信分享提示