AutoMapper.Collection.EFCore中Insert正常但Update失效问题排查
Hey there, let's break down why your InsertOrUpdate works for inserts but not updates— I spot a few critical configuration issues that are almost certainly the root cause:
1. Global NoTracking Mode Blocks EF State Tracking
The biggest culprit here is your DataContext setting:
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
When Persist().InsertOrUpdate() runs, it first queries the database to find existing entities matching your DTO. But with NoTracking enabled, EF Core doesn't monitor changes to those queried entities. Even though AutoMapper maps updated values from your DTO to the entity, EF has no way of detecting those changes— so it never generates an UPDATE statement.
Fix:
- If your application doesn't need global no-tracking, simply remove that line from your
OnConfiguringmethod. - If you must keep global no-tracking, you can explicitly enable tracking for the
Persistoperation, but the simplest fix is to disable global no-tracking for this scenario.
2. Duplicate DbContext Registrations Cause Confusion
In your Startup code, you're registering DataContext twice:
services.AddDbContext<DataContext>(); services.AddEntityFrameworkInMemoryDatabase().AddDbContext<DataContext>();
This creates multiple DataContext instances in your DI container, which means you might be operating on a different context than the one connected to your database— leading to changes not being persisted.
Fix:
- If you're using SQL Server (as seen in your
UseSqlServercall), delete theAddEntityFrameworkInMemoryDatabase()line entirely. - If you're testing with an in-memory database, keep only that registration and remove the SQL Server configuration.
3. Tweak AutoMapper Equality Comparison
While AutoMapper.Collection should automatically match entities by primary key, explicitly setting the equality comparison ensures it uses the Id field correctly for matching DTOs to existing entities:
public class AutoMapperProfile : Profile { public AutoMapperProfile() { CreateMap<ContactTestDto, Contact>() // Tell AutoMapper to match DTOs to entities by Id .EqualityComparison((dto, entity) => dto.Id == entity.Id) .ReverseMap(); } }
You only need this on the DTO-to-entity map since that's what InsertOrUpdate uses to find existing records.
4. Verify Test Logic
Double-check that you're using the same DbContext instance throughout your test, and that you're calling SaveChanges() after the InsertOrUpdate call (which you already are). Avoid mixing manual entity state changes (like setting EntityState.Modified) with the AutoMapper Persist method, as this can cause conflicts.
Side Note on Input Truncation
That odd behavior where "Hello SO-Community" gets cut to "Community" is likely a separate UI/input bug unrelated to your AutoMapper/EFCore setup— probably a quirk of the platform or tool you're using.
内容的提问来源于stack exchange,提问作者StewieG

