最重要的两个接口:
IRequest
IRequestHandler
| public class GetMoviesQuery : IRequest<IList<GetMovieDto>> { } |
| public class GetMoviesQueryHandler : IRequestHandler<GetMoviesQuery, IList<GetMovieDto>>{ |
| public async Task<IList<GetMovieDto>> Handle() |
| } |
程序整体架构图
程序流程图
| |
| { |
| "Logging": { |
| "LogLevel": { |
| "Default": "Information", |
| "Microsoft.AspNetCore": "Warning" |
| } |
| } |
| } |
| |
| |
| { |
| "ConnectionStrings": { |
| "Standard": "Server=localhost;Database=mediatr-demo;Trusted_Connection=True;" |
| }, |
| "Logging": { |
| "LogLevel": { |
| "Default": "Information", |
| "Microsoft.AspNetCore": "Warning" |
| } |
| }, |
| "AllowedHosts": "*" |
| } |
| |
| |
| <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> |
| |
| |
| using MediatR; |
| using MediatR_Demo.Repository.Context; |
| using Microsoft.EntityFrameworkCore; |
| |
| var builder = WebApplication.CreateBuilder(args); |
| |
| |
| |
| builder.Services.AddControllers(); |
| |
| |
| 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(); |
| |
| |
| if (app.Environment.IsDevelopment()) |
| { |
| app.UseSwagger(); |
| app.UseSwaggerUI(); |
| } |
| |
| app.UseHttpsRedirection(); |
| |
| app.UseAuthorization(); |
| |
| app.MapControllers(); |
| |
| app.Run(); |
| |
| |
| 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; } |
| } |
| |
| |
| 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; |
| } |
| } |
| } |
| |
| |
| 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); |
| } |
| } |
| } |
| |
| |
| 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; |
| } |
| } |
| |
| |
| |
| 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 |
| }; |
| } |
| } |
| |
| |
| 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; |
| } |
| } |
| |
| |
| using MediatR; |
| using MediatR_Demo.Domain.DTOs.Responses.Movie; |
| |
| namespace MediatR_Demo.Application.Movies.Queries.GetMovies; |
| |
| public class GetMoviesQuery : IRequest<IList<GetMovieDto>> { } |
| |
| |
| 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 |
| }; |
| } |
| } |
| |
| |
| 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; |
| } |
| } |
| |
| |
| 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); |
| } |
| } |
| |
| |
| |
| 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; } |
| } |
| } |
| |
| { |
| "$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; } |
| } |
| } |
| |
| 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 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源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实现两栏三栏布局