![](/img/trans.png)
[英]How to make EF transactional using CQRS pattern mediatr in .NET?
[英]Edit action CQRS pattern using MediatR
我有一个 .Net Core 3.1 MVC 应用程序,我正在尝试使用 CQRS 模式。 我是 MediatR 和 CQRS 模式的新手。
我的命令/查询结构是这样的:
我想使用相同的视图来创建和更新操作,因为我的类别只有两个属性。 (其中一个是Id)
我的 CategoryController.cs 文件
[HttpGet]
public IActionResult Upsert(long? id) {
if (id == null) {
//Create new, working correctly.
return View();
}
//Update existing not working.
return View(new UpsertCategoryCommand() { Id = id });
}
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesDefaultResponseType]
public async Task<IActionResult> Upsert(UpsertCategoryCommand command) {
if (ModelState.IsValid) {
await Mediator.Send(command);
return RedirectToAction(nameof(Index));
} else {
return View(command);
}
}
我的类别/索引视图在这里调用 upsert 方法。
<tbody>
@foreach (var item in Model.Categories) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.ActionLink("Edit", "Upsert", new { Id = item.Id }) |
@Html.ActionLink("Delete", "Delete", new { Id = item.Id})
</td>
</tr>
}
</tbody>
我只想将 Id 信息发送到 controller,然后我如何/在哪里映射/到达 UpsertCategoryCommand。
所有其他型号:
//UpsertCategoryCommand.cs
namespace ...Categorys.Commands.UpsertCategory {
public class UpsertCategoryCommand : IRequest<long> {
public long? Id { get; set; }
public string Name { get; set; }
public class UpsertCategoryCommandHandler : IRequestHandler<UpsertCategoryCommand, long> {
private readonly ITestDbContext _context;
public UpsertCategoryCommandHandler(ITestDbContext context) {
_context = context;
}
public async Task<long> Handle(UpsertCategoryCommand request, CancellationToken cancellationToken) {
Category entity;
if (request.Id.HasValue) {
entity = await _context.Categories.FindAsync(request.Id.Value);
} else {
entity = new Category();
_context.Categories.Add(entity);
}
entity.Name = request.Name;
await _context.SaveChangesAsync(cancellationToken);
return entity.Id;
}
}
}
}
//UpsertCategoryCommandValidator.cs
namespace ...Categories.Commands.UpsertCategory {
public class UpsertCategoryCommandValidator : AbstractValidator<UpsertCategoryCommand> {
private readonly ITestDbContext _context;
public UpsertCategoryCommandValidator(ITestDbContext context) {
_context = context;
RuleFor(x => x.Name).MaximumLength(100).NotEmpty();
RuleFor(x => x.Name)
.Must(UniqueName)
.WithMessage("Category name must be unique."); ;
}
private bool UniqueName(UpsertCategoryCommand category, string name) {
var dbCategory = _context.Categories
.Where(x => x.Name.ToLower() == name.ToLower())
.SingleOrDefault();
if (dbCategory == null)
return true;
return dbCategory.Id == category.Id;
}
}
}
//CategoryDto.cs
namespace ...Categories.Queries.GetCategoryList {
public class CategoryDto : IMapFrom<Category> {
public long Id { get; set; }
public string Name { get; set; }
public void Mapping(Profile profile) {
profile.CreateMap<Category, CategoryDto>();
}
}
}
为创建和编辑以及映射执行同一页面的最佳实践是什么? 我可以在我的命令中使用 CategoryDto 吗? 为命令和查询定义任何常见的 Dto,好吗?
我将为 CreateCategory 和 UpdateCategory 创建单独的命令,以便更清楚地了解用户的意图。 我还认为这些命令的响应应该是单独的类型,并尽量避免在命令之间重用类。
我也只会在每个命令中包含真正必要的字段,而不是尝试在各种命令中重用 CategoryDto。
所以你会有一个 CreateCategoryReponse 和 UpdateCategoryResponse 类型。 我也认为吉米在他最近的一次谈话中讨论了这个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.