abpframework / abpframework/abp

AuditLogging: EfCoreAuditLogExcelFileRepository.GetListCreationTimeBeforeAsync uses Take() without OrderBy (EF Core warning on every ExcelFileCleanupWorker run)

Open
#26,180 1 comment 0 reactions 1 assignee View on GitHub

@maliming is already working on this.

Since Sep 15, 2026.

Dominant language
C#
Stars
14.4k
Forks
3.7k
Avg merge
15h 32m
Merged PRs (30d)
106

Description

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
  1. Any ABP app with Volo.Abp.AuditLogging + EF Core (observed on 10.4.1, PostgreSQL) and the ExcelFileCleanupWorker enabled (default).
  2. Wait for the worker's period (24h by default) — or call ExcelFileDownloadService.CleanupOldFilesAsync() directly.
  3. Observe the RowLimitingOperationWithoutOrderByWarning in 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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.