Bedingte Karte "NULL" von nicht minderwertigen Typen, Aufzügen und Sammlungen mit Automapper in C#C#

Ein Treffpunkt für C#-Programmierer
Anonymous
 Bedingte Karte "NULL" von nicht minderwertigen Typen, Aufzügen und Sammlungen mit Automapper in C#

Post by Anonymous »

Übersicht
Ich entwickle einen Patch REST -Endpunkt, um eine teilweise Aktualisierung einer EF -Kernentität durchzuführen, alle Eigenschaften in der Anforderung DTO (

Code: Select all

EntityRequestDto
) sind als nullbar markiert, während die tatsächliche Entität (

Code: Select all

Entity
) wird gemäß der entworfenen Datenstruktur entweder als erforderlich oder nullbar markiert.
Die Anwendung wird unter Verwendung des Repository -Muster wird wie folgt sein:
  • Controller empfängt EntityRequestDTO über den Patch Endpunkt und übergibt es an den Dienst Layer < /li>
    Der Service empfängt EntityRequestDTO < /code>, um die folgenden Aktionen auszuführen:

    Wenden Sie sich an die Repository -Ebene, um die vorhandene Entität aus dem abzurufen Datenbank
  • MAP enttityRequestDTO zu entity (abgerufen in Schritt 2.1), um vorhandene Werte zu aktualisieren (aus Anforderung DTO an die Entität) mit Automapper
  • Validieren Code>
[*] Die Repository -Ebene empfängt die aktualisierte Entität aus der Dienstebene und speichern Änderungen in der Datenbank < /li>
< /ol>
Die obigen Schritte entsprechen dem folgenden Code: < /p>

Code: Select all

[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;
}
}
Komplikationen
Die Serviceschicht stützt sich auf Automapper, um die teilweise Aktualisierung durchzuführen, um die in der Anforderung vorhandenen Eigenschaften zu ersetzen DTO an die vorhandene Entität, während andere Eigenschaften unberührt bleiben. Modell: < /p>

Code: Select all

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!;
}
muss nach dem Zuordnen zwischen dem Anforderungs -DTO und der Entität ein teilweise Update durchführen, ansonsten null oder der Standardwert wird in die vorhanden Da sie nicht in der Anfrage DTO vorhanden sind).

Code: Select all

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>
Zusätzlich werden die folgenden Pakete im Programm verwendet und konfiguriert. 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);

// ...
}
}
Frage
Wie Sie sehen können, scheint dies eine Problemumgehung zu sein -Nullierbare Typen, Enum und Sammlungen, die im Entitätsmodell vorhanden sind. New Enum, vergessen Karte, die Eigenschaft in jedem Update ungewollt auf 0 aktualisiert)
Ich frage mich, was die richtige Methode ist, um ein teilweise Update in einem solchen Szenario mit Automapper durchzuführen?

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post