Hello,
Prior to v9.2.0, I was able to fetch data from an IRepository instance of my entity via the GetListAsync method by setting the includeDetails parameter to true. But now the method is not responding. While I am debugging, the execution gets stuck on the line where GetListAsync is called.
I tried running the SQL equivalent of it in pgAdmin. I obtain 469 lines just in seconds.
- If I downgrade the solution to v9.1.3, the method runs perfectly.
- If I remove the includeDetails parameter method continues. However it is not I want.
- Or if I change the dependency injection from IRepository<MyEntity, Guid> to IReadOnlyRepository<MyEntity, Guid> the method runs perfectly. But I don't want to change the whole solution to use IReadOnlyRepository.
If there is a better option to fix this problem please let me know. Thanks.
8 Answer(s)
-
-1
In ABP v9.2.0, if your GetListAsync(includeDetails: true) call on IRepository<MyEntity, Guid> hangs or does not respond, it is likely due to how the default WithDetails behavior is implemented for your entity's repository. When includeDetails is true, ABP calls the WithDetailsAsync method, which by default may attempt to include all navigation properties. If your entity has deep or circular relationships, or a large object graph, this can cause performance issues or even infinite loops, especially after changes in recent ABP/EF Core versions.
The IReadOnlyRepository works because it does not use the WithDetails/includeDetails mechanism in the same way, avoiding the problematic eager loading.
To resolve this, you should override the WithDetails and WithDetailsAsync methods in your custom repository implementation to explicitly specify which related entities to include, rather than relying on the default behavior. This prevents EF Core from trying to load an overly complex or circular object graph.
Example:
public class MyEntityRepository : EfCoreRepository<MyDbContext, MyEntity, Guid>, IMyEntityRepository { public MyEntityRepository(IDbContextProvider<MyDbContext> dbContextProvider) : base(dbContextProvider) { } public override IQueryable<MyEntity> WithDetails() { return GetQueryable().Include(x => x.RelatedEntity1) .Include(x => x.RelatedEntity2); // Add further .Include/.ThenInclude as needed, but avoid circular references } public override async Task<IQueryable<MyEntity>> WithDetailsAsync() { return WithDetails(); } }
Register your custom repository in the DI container and use it instead of the generic IRepository for this entity.
This approach is recommended in the official ABP documentation and best practices to avoid performance and loading issues with includeDetails.
Sources:
- ABP Entity Framework Core Integration: Loading Related Entities
- ABP Best Practices: Repository Implementation
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.
-
0
I have included related entities in the Configure<AbpEntityOptions> body in the MyEntityFrameworkCoreModule class. There are no circular references. So AI answer is not enough for me.
-
0
hi
Can you share your class code and debug logs of EF Core?
https://abp.io/support/questions/8622/How-to-enable-Debug-logs-for-troubleshoot-problems
Thanks.
-
0
This is my class code:
namespace MyApp; public class MyAppService : CrudAppService<MyEntity, MyEntityDto, Guid, GetListMyEntityDto, CreateMyEntityDto, UpdateMyEntityDto>, IMyAppService { private readonly IMyCrudEntityRepository _myCrudEntityRepository; private readonly IRepository<MyEntity, Guid> _myEntityRepository; public MyAppService(IMyCrudEntityRepository myCrudEntityRepository, IRepository<MyEntity, Guid> myEntityRepository) : base(myCrudEntityRepository) { _myEntityRepository = myEntityRepository; } public async Task GetTreeAsync() { var result = await _myEntityRepository.GetListAsync(x => x.MainId == Guid.Parse("SOME-KNOWN-GUID"), true); } }
There is no significant debug log for ef core. There are two dbCommand execution log for this request and after that no logs.
2025-06-13 11:36:07.923 +03:00 [INF] Executed DbCommand (82ms) [Parameters=[@p1='False', @tenantId='***' (Nullable = true), @p4='True', @p3='True', @mainList={ } (DbType = Object)], CommandType='"Text"', CommandTimeout='0'] SELECT a."Id", a."ConcurrencyStamp", a."RefId", a."CreatedOn", a."CreatedBy", a."ExtraProps", a."ModifiedOn", a."ModifiedBy", a."CustomParam1", a."TenantId", a."Flag1", a."FormValue", a."TailoringValue", b."Id", c."Id", d."Id", e."Id" FROM "SchemaX"."MyEntity" AS b INNER JOIN ( SELECT x."Id", x."Ref1", x."Ref2" FROM "SchemaX"."EntityA" AS x WHERE @p1 OR x."TenantId" = @tenantId ) AS c ON b."RefId" = c."Id" INNER JOIN ( SELECT y."Id" FROM "SchemaX"."EntityB" AS y WHERE (@p1 OR y."TenantId" = @tenantId) AND (@p4 OR (@p3 AND y."Id" = ANY (@mainList))) ) AS d ON c."Ref1" = d."Id" LEFT JOIN "SchemaX"."EntityC" AS e ON c."Ref2" = e."Id" INNER JOIN ( SELECT z."Id", z."ConcurrencyStamp", z."RefId", z."CreatedOn", z."CreatedBy", z."ExtraProps", z."ModifiedOn", z."ModifiedBy", z."CustomParam1", z."TenantId", z."Flag1", z."FormValue", z."TailoringValue" FROM "SchemaX"."EntityD" AS z WHERE @p1 OR z."TenantId" = @tenantId ) AS a ON c."Id" = a."RefId" WHERE (@p1 OR b."TenantId" = @tenantId) AND (@p4 OR (@p3 AND b."MainId" = ANY (@mainList))) AND b."MainId" = '***' ORDER BY b."Id", c."Id", d."Id", e."Id"
2025-06-13 11:36:10.038 +03:00 [INF] Executed DbCommand (71ms) [Parameters=[@p1='False', @tenantId='***' (Nullable = true), @p4='True', @p3='True', @mainList={ } (DbType = Object)], CommandType='"Text"', CommandTimeout='0'] SELECT a."Id", a."ForeignKey1", a."ConcurrencyStamp", a."RefId", a."CreatedOn", a."CreatedBy", a."ExtraProps", a."ModifiedOn", a."ModifiedBy", a."TenantId", a."Id0", a."Explanation", a."IdentNumber", a."Text", a."RefX", a."FlagX", a."ConcurrencyStamp0", a."CreatedOn0", a."CreatedBy0", a."ExtraProps0", a."IsPending", a."ModifiedOn0", a."ModifiedBy0", a."RefMain", a."TenantId0", a."Title", b."Id", c."Id", d."Id", e."Id" FROM "SchemaX"."MyEntity" AS b INNER JOIN ( SELECT x."Id", x."Ref1", x."Ref2" FROM "SchemaX"."EntityA" AS x WHERE @p1 OR x."TenantId" = @tenantId ) AS c ON b."RefId" = c."Id" INNER JOIN ( SELECT y."Id" FROM "SchemaX"."EntityB" AS y WHERE (@p1 OR y."TenantId" = @tenantId) AND (@p4 OR (@p3 AND y."Id" = ANY (@mainList))) ) AS d ON c."Ref1" = d."Id" LEFT JOIN "SchemaX"."EntityC" AS e ON c."Ref2" = e."Id" INNER JOIN ( SELECT z."Id", z."ForeignKey1", z."ConcurrencyStamp", z."RefId", z."CreatedOn", z."CreatedBy", z."ExtraProps", z."ModifiedOn", z."ModifiedBy", z."TenantId", zz."Id" AS "Id0", zz."Explanation", zz."IdentNumber", zz."Text", zz."RefX", zz."FlagX", zz."ConcurrencyStamp" AS "ConcurrencyStamp0", zz."CreatedOn" AS "CreatedOn0", zz."CreatedBy" AS "CreatedBy0", zz."ExtraProps" AS "ExtraProps0", zz."IsPending", zz."ModifiedOn" AS "ModifiedOn0", zz."ModifiedBy" AS "ModifiedBy0", zz."RefMain", zz."TenantId" AS "TenantId0", zz."Title" FROM "SchemaX"."EntityE" AS z INNER JOIN ( SELECT zz."Id", zz."Explanation", zz."IdentNumber", zz."Text", zz."RefX", zz."FlagX", zz."ConcurrencyStamp", zz."CreatedOn", zz."CreatedBy", zz."ExtraProps", zz."IsPending", zz."ModifiedOn", zz."ModifiedBy", zz."RefMain", zz."TenantId", zz."Title" FROM "SchemaX"."EntityF" AS zz WHERE @p1 OR zz."TenantId" = @tenantId ) AS zz ON z."ForeignKey1" = zz."Id" WHERE @p1 OR z."TenantId" = @tenantId ) AS a ON c."Id" = a."RefId" WHERE (@p1 OR b."TenantId" = @tenantId) AND (@p4 OR (@p3 AND b."MainId" = ANY (@mainList))) AND b."MainId" = '***' ORDER BY b."Id", c."Id", d."Id", e."Id"
I obfuscated SQL query to hide sensitive table and column names via AI.
-
0
hi
Your code looks fine. Could you share a project that can reproduce the problem?
I'll download it and take a look.
liming.ma@volosoft.com
Thanks.
-
0
Hi,
I can't obfuscate whole project. If we can arrange an online meeting I'll show it there.
-
0
hi
Can you copy your code to a new template project and share it?
I need to debug it on my local.
Thanks.
-
0
Is your problem fixed? if yes, how it was fixed?