u/ExpressionVsitor

[Library] Avoiding combinatorial explosion in EF Core repositories
▲ 8 r/csharp

[Library] Avoiding combinatorial explosion in EF Core repositories

Hey guys!

I’ve been working on a library called QChain focused on reusable and composable DAL queries on top of LINQ and EF Core.

Main goal:
avoid duplicated joins, filters, projections, and repository method explosion in larger applications.

Instead of composing everything directly on IQueryable<T> with anonymous intermediate shapes, queries become reusable pipelines returning IQuery<T>.

Example:

public IQuery<(Account account, Order order)> ActiveEuropeanOrdersInLastMonth() =>
    db.Accounts
        .Join(db.Orders,
            a => a.AccountId,
            o => o.AccountId,
            (a, o) => ValueTuple.Create(a, o))
        .Where(x => x.account.IsActive().And(x.order.InLastMonth()));

Then later:

OrderDto[] orders = await unitOfWork.Query(db =>
        db.AccountsRepository.ActiveEuropeanOrdersInLastMonth()
            .Select(x => new OrderDto(x.order.OrderId, x.account.Email))
            .Skip(index * size)
            .Take(size))
    .ToArrayAsync();

A big focus was preserving composability across joins/grouping while still translating correctly through EF Core.

Features:

  • reusable predicates/specifications
  • composable query pipelines
  • tuple-based intermediate query shapes
  • deferred execution
  • EF Core integration
  • escape hatch back to IQueryable<T> via AsQueryable()

Repo:
https://github.com/MihaiBratulescu/QChain

Would love feedback, especially from people dealing with large EF Core/repository/specification-heavy codebases.

u/ExpressionVsitor — 13 days ago