在我的web应用程序中,我有一个具有许多属性的类。用户可以通过一堆选择框来修改这些属性,每个选择框负责一个属性。每次更改给定属性时,都会触发更改事件,ajax会将此属性的新值发送到Controller中的Update方法。
到目前为止,我有一个UpdateDto,它由可为null的字段组成。在我的更新控制器中,我检查每个DTO的字段是否为空。若它不为null,则表示用户想要更改此属性,并将其更新并保存在数据库中。
不幸的是,Update方法的代码对我来说有点难看。它检查每个属性,而且很长。看看:
控制器中的更新方法:
public IHttpActionResult UpdateScrumTask(int id, ScrumTaskDetailsDto scrumTaskDto)
{
var scrumTaskFromDb = _context.ScrumTasks
.SingleOrDefault(s => s.Id == id);
if (scrumTaskFromDb == null)
return NotFound();
if (!ModelState.IsValid)
return BadRequest();
if (!string.IsNullOrWhiteSpace(scrumTaskDto.UserId))
{
var user = _context.Users
.SingleOrDefault(u => u.Id.Equals(scrumTaskDto.UserId));
scrumTaskFromDb.UserId = user?.Id;
}
else if (scrumTaskDto.EstimationId != null)
{
var estimation = _context.Estimations
.SingleOrDefault(u => u.Id == scrumTaskDto.EstimationId.Value);
scrumTaskFromDb.EstimationId = estimation?.Id;
}
else if (scrumTaskDto.Priority != null)
{
if (scrumTaskDto.Priority.Value == 0)
scrumTaskDto.Priority = null;
scrumTaskFromDb.Priority = scrumTaskDto.Priority;
}
else if (scrumTaskDto.TaskType != null)
{
scrumTaskFromDb.TaskType = scrumTaskDto.TaskType.Value;
}
_context.SaveChanges();
return Ok();
}
更新DTO:
public class ScrumTaskDetailsDto
{
public int? EstimationId { get; set; }
[Range(0, 5)]
public byte? Priority { get; set; }
[Range(0, 2)]
public TaskType? TaskType { get; set; }
public string UserId { get; set; }
}
请注意,这些属性在数据库中也可以为null。这就是为什么,例如,如果找不到UserId,则数据库中的属性将设置为null。
我想知道它应该是什么样子。什么是更好的解决方案?
- 保留一个Update方法,并使用一个UpdateDto与多个可为null的字段OR
- 将Update方法设计为多个方法,每个方法负责一个属性并创建单独的DTO。它带来了将有许多DTO与一个具有单一属性的模型连接(这好吗?)
另一个问题是:我应该在DTO中使用validtion(DataAnnotation)吗?如果没有,替代方案是什么?
我建议几个改进:
- 使用存储库模式或使用MediatR之类的库的查询和命令对象,将查询逻辑与核心业务逻辑分离,并且控制器只应调用其他方法为其做一些事情并返回响应,它不应具有任何查询或任何其他逻辑
- DTO在我看来还可以,只要它围绕着一个特定的任务
- 我肯定会把更新和控制器分开,因为它是一个或多个方法,有35…行,这并不理想,也许你可以把它分成两个方法,一个负责验证,一个用于实际更新,你也可以使用依赖注入将更新和验证方法与控制器解耦