ASP.NET Core 3.1. 컬렉션 업데이트 문제

Nov 14 2020

ASP.NET Core의 애플리케이션을 2.1에서 3.1로 마이그레이션하고 Entity Framework에 문제가 있습니다.

GlassesLenses컬렉션 이있는 엔터티가 있습니다.

public class GlassesContract : BaseUpdateEntity, IAggregateRoot
{
    public Guid Id { get; private set; } = Guid.NewGuid();

    private readonly List<GlassesLenses> _glassesLenses = new List<GlassesLenses>();
    public ICollection<GlassesLenses> GlassesLenses => _glassesLenses.AsReadOnly().ToList();

    public void ClearLenses()
    {
        _glassesLenses.RemoveRange(0, _glassesLenses.Count);
    }

    public void AddLens(GlassesLenses lens)
    {
        _glassesLenses.Add(lens);
    }
}

렌즈 업데이트 서비스 :

public async Task<GlassesContract> ChangeSetting(GlassesContract contract)
{
    // clean lenses
    contract.ClearLenses();
    await _glassesContractRepository.UpdateAsync(contract);

    // add new lens
    contract.AddLens(new GlassesLenses());

    await _glassesContractRepository.UpdateAsync(contract);
    return contract;
}

버전 2.1에서는 동작이 잘 작동합니다. 컬렉션이 지워지고 (EF는 삭제를 위해 엔티티를 표시 함) 삽입을위한 새 엔티티로 새 렌즈 EF 마크를 추가 한 후

버전 3.1에서는 삭제 및 삽입 대신 EF Core가 업데이트 만 수행합니다.

// delete lens
UPDATE public."GlassesContracts" 
SET "AccountId" = @p0, "BalancePaymentDeposit" = @p1, ...
WHERE "Id" = @p42 AND "SysRowVer" IS NULL
RETURNING "SysRowVer";

// add new lens
UPDATE public."GlassesContracts" 
SET "AccountId" = @p0, "BalancePaymentDeposit" = @p1, ...
WHERE "Id" = @p42 AND "SysRowVer" IS NULL
RETURNING "SysRowVer";

UPDATE public."GlassesLenses" 
SET "Availability" = @p43, "Color" = @p44, ...
WHERE "Id" = @p77 AND "SysRowVer" IS NULL
RETURNING "SysRowVer";

DbContext 매핑 :

// mapping relationship
    modelBuilder.Entity<GlassesContract>()
      .HasMany(_ => _.GlassesLenses)
      .WithOne(_ => _.GlassesContract)
      .OnDelete(DeleteBehavior.Cascade);
    
    modelBuilder.Entity<GlassesLenses>()
      .HasOne(_ => _.GlassesContract)
      .WithMany(_ => _.GlassesLenses);

// mapping Value objects
modelBuilder.Entity<GlassesLenses>().OwnsOne(o => o.Price).WithOwner();
modelBuilder.Entity<GlassesLenses>().OwnsOne(o => o.PriceExclVat).WithOwner();
modelBuilder.Entity<GlassesLenses>().OwnsOne(o => o.FinalPrice).WithOwner();
modelBuilder.Entity<GlassesLenses>().OwnsOne(o => o.FinalPriceExclVat).WithOwner();
modelBuilder.Entity<GlassesLenses>().OwnsOne(o => o.Discount).WithOwner();

엔티티를 AddAsync(entity)또는로 표시하면 Remove(entity)올바른 SQL이 INSERT 및 DELETE로 생성됩니다.

새 버전 3.1이 v2.1만큼 똑똑하지 않은 이유와 SysRowVer(동시성 토큰)이 항상 NULL이고 업데이트되지 않는 이유를 설명 할 수 있습니까 ?

정말 고맙습니다

최신 정보

엔터티 추적기는 AddLens (..) 호출 후 '엔티티 GlassesLens가 수정 됨'이라고 말합니다. 왜 새로운 것으로 추가되었는지 이해할 수 없습니다.

--- 해결 ----

답변

ash Nov 15 2020 at 00:44

EF 데이터베이스 컨텍스트 테이블 매핑 사용

modelBuilder.Entity<GlassesContract >(m =>
{
        m.OwnsMany(i => i.GlassesLenses); //instead of HasMany().WithOne()
});

OwnsMany에 대한 자세한 설명은이 SO를 확인하십시오.

daremachine Nov 15 2020 at 01:55

해결책을 찾았습니다 (내 지식 실수). 문제는 EF Core 3+의 주요 변경 사항입니다.

GUID를 기본 키로 사용하고 있습니다. DDD 규칙 및 엔티티 프레임 워크를 사용하는 애플리케이션이이 동작을 변경했기 때문에 이는 생성 된 값이 아닙니다.

DatabaseGenerated속성 추가로 ID가 생성되지 않았 음을 EF에 알려야 합니다.

[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; private set; } = Guid.NewGuid();

또는 DbContext에 능통

modelBuilder
    .Entity<GlassesLenses>()
    .Property(e => e.Id)
    .ValueGeneratedNever();

신의 축복 이 게시물

그리고 원본은

DetectChanges는 저장소 생성 키 값을 준수합니다.

모두 감사합니다