Здравствуйте, я разрабатываю патч конечную точку REST для частичного обновления для EF Core Entity, все свойства в запросе DTO (
Код: Выделить всё
EntityRequestDtoКод: Выделить всё
EntityПриложение разработано с использованием шаблона репозитория (контроллер> служба> Репозиторий), поэтому поток обновления будет похоже на это:
- Контроллер получает EntityRequestdto через конечную точку Patch и передает ее в службу Layer < /li>
Служба получает EntityRequestDto < /code> для выполнения следующих действий:
Свяжитесь с уровнем репозитория, чтобы получить существующую сущность из База данных - map entityrequestdto to entity (получено в шаге 2.1) для обновления существующих значений (Из запроса DTO к объекту) с использованием Automapper
- Проверьте обновленную сущность
- Свяжитесь с уровнем хранилища, чтобы снова сохранить изменения, внесенные в Entity
< /ol>
Приведенные выше шаги равны следующему коду: < /p>
Код: Выделить всё
[Authorize]
[Route("[controller]")]
public class EntityController(IEntityService service) : ControllerBase
{
[HttpPatch("{id}")]
public IActionResult Update(Guid id, [FromBody] EntityRequestDto requestDto) =>
Ok(service.UpdateAsync(id, requestDto).Result);
}
public class EntityService(IEntityRepository repository): IEntityService
{
public async Task UpdateAsync(Guid id, EntityRequestDto requestDto)
{
var existingEntity = await repository.GetAsync(id);
if (existingEntity is null) return null;
mapper.Map(requestDto, existingEntity);
await validator.ValidateAndThrowAsync(existingEntity);
await repository.UpdateAsync(existingEntity);
return mapper.Map(existingEntity);
}
}
public class EntityRepository(EntityContext context) : IEntityRepository
{
public async Task UpdateAsync(Entity entity)
{
await _context.SaveChangesAsync();
return entity;
}
}
< /code>
осложнений < /h2>
Служба полагается на автоматиптель, чтобы сделать частичное обновление, чтобы помочь заменить свойства, присутствующие в Запросить DTO существующей сущности, оставляя другие свойства нетронутыми. модель сущности: < /p>
public enum EntityType {
TYPE_1,
TYPE_2
}
public class Entity {
public required Guid Id { get; set; }
public required EntityType Type { get; set; }
public required int IntegerProperty { get; set; }
public required string StringProperty { get; set; }
public List EntityItems { get; set; } = [];
}
public class EntityRequestDto {
public EntityType? Type { get; set; }
public int? IntegerProperty { get; set; }
public string? StringProperty { get; set; }
public List EntityItems { get; set; } = null;
}
public class EntityItems {
public required Guid Id { get; set; }
public required string Name { get; set; }
public required Guid EntityId { get; set; }
public Entity Entity { get; set; } = null!;
}
Код: Выделить всё
public class Mapper : Profile
{
public Mapper()
{
// If an integer property in the request DTO is `null`, do not map and preserve the value from the existing entity (prevent the default value of `0` get mapped into the entity)
profile.CreateMap().ConvertUsing((src, dest) => src ?? dest);
// If an enum property in the request DTO is `null`, do not map and preserve the value from the existing entity (prevent the default value of first enum constant or position `0` get mapped into the entity)
profile.CreateMap().ConvertUsing((src, dest) => src ?? dest);
// If `EntityItems` from the `EntityRequestDto` is `null`, do not map it to the entity (which will remove all existing items in the entity)
profile.CreateMap().ForMember(dest => dest.EntityItems, opt =>
{
opt.PreCondition((src) => src.EntityItems != null);
opt.MapFrom(src => src.EntityItems);
});
// For other properties, do not map if the value in the `EntityRequestDto` is `null`
profile.CreateMap().PreserveReferences()
.EqualityComparison((requestDto, entity) => requestDto.Id == entity.Id)
.ForAllMembers(option => option.Condition((_, _, sourceMember) => sourceMember != null));
}
}
< /code>
Кроме того, используются и настроены следующие пакеты в программе. Automapper < /li>
automapper.collection.entityFrameWorkCore
< /ul>
public static class Program
{
private static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAutoMapper((serviceProvider, config) =>
{
config.AddCollectionMappers();
config.UseEntityFrameworkCoreModel(serviceProvider);
}, typeof(Mapper).Assembly);
// ...
}
}
< /code>
Вопрос < /h2>
Как вы можете видеть, это кажется обходным путем, потому что одному объекту требуется несколько отображений для Не нулевые типы, перечисление и коллекции, которые присутствуют в модели объекта. новый enum, забыл карту, свойство непреднамеренно обновляется до 0 Мне интересно, что является правильным методом для выполнения частичного обновления в таком сценарии, подобном этому, используя Automapper?
Подробнее здесь: https://stackoverflow.com/questions/794 ... ith-automa