AuditLogging: EfCoreAuditLogExcelFileRepository.GetListCreationTimeBeforeAsync uses Take() without OrderBy (EF Core warning on every ExcelFileCleanupWorker run)
Summary
EfCoreAuditLogExcelFileRepository.GetListCreationTimeBeforeAsync applies Take(maxResultCount) without an OrderBy, so every run of ExcelFileCleanupWorker emits the EF Core warning:
The query uses a row limiting operator ('Skip'/'Take') without an 'OrderBy' operator. This may lead to unpredictable results. ...Source (current dev):
https://github.com/abpframework/abp/blob/dev/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogExcelFileRepository.cs
return await queryable
.Where(x => x.CreationTime < creationTimeBefore)
.Take(maxResultCount)
.ToListAsync(cancellationToken);Reproduction
- Any ABP app with
Volo.Abp.AuditLogging+ EF Core (observed on 10.4.1, PostgreSQL) and theExcelFileCleanupWorkerenabled (default). - Wait for the worker's period (24h by default) — or call
ExcelFileDownloadService.CleanupOldFilesAsync()directly. - Observe the
RowLimitingOperationWithoutOrderByWarningin the logs, once per cleanup run, right between the "File cleanup worker started/finished" lines.
Impact
Functionally benign — the caller loops in batches of 100 until nothing older than the cutoff remains, so ordering does not affect which rows are eventually deleted. But it is a guaranteed daily warning in production logs, and it is indistinguishable from the same warning raised by real unordered paging in application code, so it trains people to ignore a signal that matters.
Suggested fix
return await queryable
.Where(x => x.CreationTime < creationTimeBefore)
.OrderBy(x => x.CreationTime)
.Take(maxResultCount)
.ToListAsync(cancellationToken);Oldest-first also makes the batch deletion deterministic. The MongoDB implementation would want the same for consistency.
Environment
- ABP 10.4.1,
Volo.Abp.AuditLogging.*, EF Core + Npgsql, .NET 10
Source: abpframework/abp