Hi,
We're using ABP with EFCore to SQL Server (using an Angular frontend). All our entities are FullAuditedXXXWithUser<long, IdentityUser>. The LastModificationTime is not always updated, specially when updating a relationship.
For example,: we have a book with one author (one-to-many. Book has a field long? AuthorId {get;set;}).
When updating some fields from book, the modification fields are updated.
When only updating the author (choosing a new author from the dropdown), the modification fields are not updated. We expected those auditfields to be updated.
Is there some (undocumented) configuration we need to do, or a bug?
We've created a new simple ABP project to reproduce, and the same behaviour happens.
- Template: app
- Created ABP Studio Version: 1.1.2
- Current ABP Studio Version: 1.4.1
- Tiered: No
- Multi-Tenancy: No
- UI Framework: angular
- Theme: leptonx
- Theme Style: system
- Theme Menu Placement: side
- Run Install Libs: Yes
- Progressive Web App: No
- Run Progressive Web App Support: No
- Database Provider: ef
- Database Management System: sqlserver
- Separate Tenant Schema: No
- Create Initial Migration: Yes
- Run Db Migrator: Yes
- Mobile Framework: none
- Public Website: No
- Social Login: No
- Include Tests: Yes
- Kubernetes Configuration: No
- Distributed Event Bus: none
- Use Local References: No
- Optional Modules:
- GDPR
- TextTemplateManagement
- LanguageManagement
- AuditLogging
- OpenIddictAdmin
 
- Selected Languages: Dutch, English, Français
- Default Language: Dutch
- Create Command: abp new AbpShowcase -t app --ui-framework angular --database-provider ef --database-management-system sqlserver --theme leptonx --without-cms-kit --sample-crud-page --dont-run-bundling --no-multi-tenancy --no-social-logins -no-saas -no-file-management
- Exception message and full stack trace: NA
- Steps to reproduce the issue:
- In a new ABP Project (Angular, EF Core to SQL Server) and create two FullAuditedAggregates with a one-to-many relationship (eg. a book has one author)
- The should be a field public long? AuthorId {get;set;}
 
- The should be a field 
- On the detailscreen of book, choose another author. (update only this one-to-many property!)
- ==> Auditfields LastModificationTime and LastModifier are not updated.
 
- In a new ABP Project (Angular, EF Core to SQL Server) and create two FullAuditedAggregates with a one-to-many relationship (eg. a book has one author)
3 Answer(s)
- 
    0- Solution
 - Root cause - In ABP, modification audit properties (LastModificationTime/LastModifierId) are set by ApplyAbpConcepts during SaveChanges only when EF Core reports the entity as Modified. Historically, changing only a navigation/foreign key could be missed by EF change detection, so audit fields were not updated.
- From ABP 8.3 onward, the framework explicitly updates ModificationAuditProperties when a navigation property changes. On earlier versions (like 9.2.3 is newer than 8.3, so it already includes this behavior), you should get updates if the FK or navigation change is tracked as a modification within the same DbContext/Unit of Work.
 
- What to verify in your app - Ensure updates happen inside a Unit of Work and the same DbContext instance tracks the entity and the FK change before SaveChanges.
- Use repository.GetAsync(id), mutate tracked entity’s AuthorId (or navigation), then await repository.UpdateAsync(entity, autoSave: true) or rely on UoW completion.
 
- Change the FK scalar property, not only the navigation proxy:
 
- Ensure updates happen inside a Unit of Work and the same DbContext instance tracks the entity and the FK change before SaveChanges.
 var book = await _bookRepository.GetAsync(id); book.AuthorId = input.AuthorId; // set the FK scalar // or set book.Author = await _authorRepository.GetAsync(input.AuthorId); await _bookRepository.UpdateAsync(book, autoSave: true);- Do not use ExecuteUpdate/ExecuteDelete bulk operations for this scenario; they bypass EF tracking, so ABP auditing (including modification audit fields) will not run.
- Make sure CurrentUser is available if you expect LastModifierId. If the operation is AllowAnonymous or executed by background processes, LastModifierId may be null unless you set a principal:
 var claims = new List<Claim> { new Claim(AbpClaimTypes.UserId, userId.ToString()) }; using (_currentPrincipalAccessor.Change(claims)) { await _bookRepository.UpdateAsync(book, autoSave: true); }- If you’re attaching a detached entity (e.g., mapping DTO to new entity instance and calling UpdateAsync), ensure EF knows which properties changed. Prefer fetch-and-mutate; otherwise you may need to mark the FK property as modified on the DbContext entry.
 - ABP 8.3+ behavior (applies to 9.2.3) - ABP updates ModificationAuditProperties when navigation properties change. If you still see no update:
- Confirm that AuthorId change results in EF change tracker marking the entity as Modified.
- Confirm the change is not done via raw SQL or bulk update APIs.
- Confirm the update path is not suppressing ApplyAbpConcepts (e.g., custom DbContext SaveChanges override that skips base behavior).
 
 
- ABP updates ModificationAuditProperties when navigation properties change. If you still see no update:
- Minimal working example 
 public class BookAppService : ApplicationService { private readonly IRepository<Book, long> _bookRepository; public BookAppService(IRepository<Book, long> bookRepository) { _bookRepository = bookRepository; } public async Task UpdateAuthorAsync(long id, long? newAuthorId) { var book = await _bookRepository.GetAsync(id); // tracked book.AuthorId = newAuthorId; await _bookRepository.UpdateAsync(book, autoSave: true); // triggers ApplyAbpConcepts // After save, LastModificationTime and LastModifierId should be updated (if CurrentUser.Id exists) } }- If you must use detached updates
 var book = await _bookRepository.GetAsync(id); _ = ObjectMapper.Map(input, book); // ensure AuthorId ends up different await _bookRepository.UpdateAsync(book, autoSave: true);- Summary
- With ABP 9.2.3, changing a FK/navigation should update LastModificationTime/LastModifierId provided:
- The change is tracked by EF in a normal UoW (not bulk ops/raw SQL).
- You change the entity instance fetched from repository (tracked).
- CurrentUser is set if you expect LastModifierId.
 
- If your code path still does not update the audit fields, refactor to fetch-and-mutate within the repository/UoW as shown above.
 
- With ABP 9.2.3, changing a FK/navigation should update LastModificationTime/LastModifierId provided:
 - Sources
 - https://abp.io/docs/latest/release-info/migration-guides/abp-8-3
- https://abp.io/support/questions/6298
- https://abp.io/community/articles/zvr01mtn
 
 This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon. 
- 
    0Hi, We already tried suggestions of the AI-bot . - We are updating by ID. (no navigation property). In EF Core, the Id is configured as a foreign key by default.
- We are using the default generated code from ABP-Suite. So tracked entity, explicit update. Not directly on the database.
 
- 
    0hi We've created a new simple ABP project to reproduce, and the same behaviour happens. Can you share the test project to liming.ma@volosoft.com? Thanks. 
 
                                