Użycie automappera do edycji istniejącej pozycji

0

Hej,

poniżej moje POCO

public class Order
{
    public int Id { get; set; }
    
    public int CustomerId { get; set; }
    public Customer Customer { get; set; }        
    
    public int TargetCustomerId { get; set; }
    public Customer TargetCustomer { get; set; }
    
    public int AddressId { get; set; }
    public Address Address { get; set; }

    public DateTime IssueDate { get; set; } = DateTime.Now;
    public DateTime RealizationDate { get; set; }
    public DateTime DueDate { get; set; }
    public int DueDays { get; set; }    
    public OrderStatus Status { get; set; }
    public string? Comments { get; set; }

    public int UserId { get; set; }
    public User User { get; set; }

    public List<OrderPosition> Positions { get; set; }
}
public class OrderPosition
{
    public int Id { get; set; }

    public int SkuId { get; set; }
    public Sku Sku { get; set; }
    
    [Column(TypeName = "decimal(11,4)")]
    public decimal quantity { get; set; }
    
    [Column(TypeName = "decimal(15,4)")]
    public decimal price { get; set; }

    [Column(TypeName = "decimal(5,2)")]
    public decimal discount { get; set; }

    public int OrderId { get; set; }
    public Order Order { get; set; }        
}

oraz DTO

public class OrderRequest
{
    public int CustomerId { get; set; }
    public int TargetCustomerId { get; set; }
    public int AddressId { get; set; }
    public DateTime RealizationDate { get; set; }
    public DateTime DueDate { get; set; }
    public OrderStatus Status { get; set; }
    public string? Comments { get; set; }
    public List<OrderPositionDto> Positions { get; set; }
}

public class OrderPositionDto
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
    public string CodeName { get; set; }
    public string Uom { get; set; }
    public decimal Quantity { get; set; }
    public decimal Price { get; set; }
    public decimal Discount { get; set; }
}

Automapperem zrobiłem coś takiego

CreateMap<OrderRequest, Order>();
CreateMap<OrderPositionDto, OrderPosition>()
    .ForMember(m => m.SkuId, c => c.MapFrom(c => c.Id))
    .ForMember(m => m.Id, c => c.Ignore());

mój serwis do edycji

public bool EditOrder(OrderRequest orderRequest, int id)
{
    var order = _dbContext.Orders.Include(p => p.Positions).SingleOrDefault(c => c.Id == id);

    if (order is null)
        return false;

    _mapper.Map(orderRequest, order);

    _dbContext.SaveChanges();

    return true;
}

wszystko ładnie działa NO ALE: gdy wchodzę na zamówienie i zmienię np. zamawianą ilość skutkuje to usunięciem pozycji i dodaniem nowej ( nowe id ) i zmienioną ilością.
Nie wiem czy to jest OK w EF czy nie powinno tak się dziać i coś mam nie tak?

1

Przed SaveChanges możesz wstawic i zobaczyć co się dzieję:

_dbContext.ChangeTracker.DetectChanges();
Console.WriteLine(_dbContext.ChangeTracker.DebugView.LongView);

Według mnie podczas:

  var order = _dbContext.Orders.Include(p => p.Positions).SingleOrDefault(c => c.Id == id);

encja jest pobierana i śledzona podczas przez EF.

Podczas:

_mapper.Map(orderRequest, order);

Order jest aktualizowany, ale OrderPosition jest usuwany i tworzony od nowa przez mappera. Dlatego EF widzi że obiekt został usunięty i dodany jeszcze raz.

1

wydaje mi sie, ze brakuje Ci [key] na Id, przez co pewnie to jest inna instancja (musisz skonfigurowac tak, zeby changetracker wiedzial jak porownac encje)

0

Nie tyle że brakuje [Key] bo "Id" jest domyślnie mapowane na PK, ale wartość Id z DTO musi być zmapowana do Id w POCO.
Chyba też trzeba pokazać jawnie, że Positions też trzeba dodać/zaktualizować. Np. ustawiając EntityState

Ja mam takie coś. Jeśli w Modelu Id > 0 to jest update a jeśli 0 to nowy obiekt.

public async Task<ConfigModel> Update(ConfigModel model)
        {
            
            var c = _mapper.Map<Config>(model);
            var db = await _dbFactory.CreateDbContextAsync();
            db.Entry(c).State = c.Id > 0 ? EntityState.Modified : EntityState.Added;
            await db.SaveChangesAsync();
            return _mapper.Map<ConfigModel>(c);
        }

1 użytkowników online, w tym zalogowanych: 0, gości: 1