I migrating application in ASP.NET Core from 2.1 to 3.1 and have problems with Entity Framework.
I have an entity with GlassesLenses collection:
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);
}
}
And a service for updating lenses:
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;
}
In version 2.1 the behaviour is working fine. The collection was cleared (EF marks entity for delete) and after add new lens EF mark as new entity for insert.
In version 3.1, instead of delete and insert, EF Core only does an update.
// 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";
Mapping 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();
If I mark entity with AddAsync(entity) or Remove(entity) this will generate right SQL as INSERT and DELETE.
Can you anyone explain why the new version 3.1 is not as smart as v2.1 and why SysRowVer (concurrency token) is always NULL and not updated?
Thank you so much
UPDATE
The entity tracker says 'entity GlassesLens is modified' after AddLens(..) call. I don't understand why if is added as new.
---SOLVED---