Skip to content

Conversation

@mitchelsellers
Copy link
Contributor

@mitchelsellers mitchelsellers commented Dec 6, 2025

Initial round of helpers to streamline LINQ & EFCore Queries

Summary by CodeRabbit

  • New Features

    • Added conditional query filtering and conditional ordering options.
    • Added paging support for queries.
    • Added distinct-by-key projection for query results.
  • Tests

    • Added unit tests validating conditional filtering, conditional ordering, paging behavior, and distinct projection across scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

- Fixes #70

Initial round of helpers to streamline LINQ & EFCore Queries
@mitchelsellers mitchelsellers added the enhancement New feature or request label Dec 6, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 6, 2025

Walkthrough

Adds a new QueryableExtensions static class with five IQueryable helpers (WhereIf, OrderByIf, OrderByDescendingIf, GetPage, DistinctBy) and a corresponding test suite that exercises conditional filtering, conditional ordering, paging, and distinct projection across an in-memory dataset.

Changes

Cohort / File(s) Summary
QueryableExtensions Implementation
src/NetCore.Utilities/QueryableExtensions.cs
Adds a new static utility class with five extension methods for IQueryable: WhereIf, OrderByIf, OrderByDescendingIf, GetPage (1-based paging via Skip/Take), and DistinctBy (via GroupBy/First). Includes XML doc comments.
QueryableExtensions Tests
src/NetCore.Utilities.Tests/QueryableExtensionsTests.cs
Adds unit tests defining a TestEntity, building an in-memory dataset, and validating WhereIf, OrderByIf, OrderByDescendingIf, GetPage, and DistinctBy behaviors (asserting IDs/names and deterministic ordering).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review extension method correctness and null/argument handling in QueryableExtensions.cs.
  • Validate test coverage and deterministic ordering assumptions in QueryableExtensionsTests.cs.

Poem

🐰 I nibble on LINQ, hop through each line,

WhereIf and OrderBy, the queries align.
Pages I fetch, distinct carrots I find,
Clean trails of code, neat and refined. 😊

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Out of Scope Changes check ❓ Inconclusive The PR includes two additional extension methods (GetPage, DistinctBy) beyond the scope defined in issue #70, though these are complementary LINQ helpers. Clarify whether GetPage and DistinctBy should be included in this PR or deferred to a future issue, as they extend beyond the three methods specified in issue #70.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding new Queryable extension methods to the codebase.
Linked Issues check ✅ Passed The PR implements all three required extension methods (WhereIf, OrderByIf, OrderByDescendingIf) from issue #70, with comprehensive tests validating their behavior.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/iqueryable-extensions

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d69b800 and 81db13c.

📒 Files selected for processing (1)
  • src/NetCore.Utilities.Tests/QueryableExtensionsTests.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/NetCore.Utilities.Tests/QueryableExtensionsTests.cs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze Code Quality

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (4)
src/NetCore.Utilities.Tests/QueryableExtensionsTests.cs (4)

29-46: Consider adding edge case tests.

The current tests cover the happy path well, but consider adding tests for:

  • Null parameter handling (once null validation is added to the implementation)
  • Empty queryable sequences
  • Multiple chained WhereIf calls

Example test for empty queryable:

[Fact]
public void WhereIf_EmptyQueryable_ReturnsEmpty()
{
    var query = Enumerable.Empty<TestEntity>().AsQueryable();
    var result = query.WhereIf(true, x => x.Name == "Alpha").ToList();
    
    Assert.Empty(result);
}

48-82: LGTM! Consider adding edge case tests for consistency.

The ordering tests are well-structured and cover both conditional branches effectively. For consistency with other test methods, consider adding edge case tests (null parameters, empty queryables) once the implementation adds proper validation.


95-106: Test doesn't verify deterministic element selection.

The test confirms that distinct names are returned but doesn't verify which specific element is selected when duplicates exist (e.g., which "Alpha" entity—Id 1 or Id 4—is returned). This masks the non-deterministic behavior of the GroupBy().Select(x => x.First()) implementation.

Consider adding a test that verifies deterministic behavior:

[Fact]
public void DistinctBy_ConsecutiveRuns_ReturnsSameElements()
{
    var query = GetTestEntities();
    
    var result1 = query.DistinctBy(x => x.Name).OrderBy(x => x.Name).ToList();
    var result2 = query.DistinctBy(x => x.Name).OrderBy(x => x.Name).ToList();
    
    // Verify same IDs are returned for duplicate names
    Assert.Equal(result1.Select(x => x.Id), result2.Select(x => x.Id));
}

Note: This test may fail with the current implementation if the underlying query execution order changes.


1-107: Consider expanding test coverage for robustness.

The test suite provides good coverage of happy path scenarios. To improve robustness, consider adding:

  1. Null parameter tests for all methods (once validation is added)
  2. Edge case tests for boundary conditions
  3. Tests with empty queryables
  4. Tests for method chaining scenarios (e.g., WhereIf().OrderByIf())

Example method chaining test:

[Fact]
public void MultipleExtensions_Chained_WorksCorrectly()
{
    var query = GetTestEntities();
    var result = query
        .WhereIf(true, x => x.Name != "Gamma")
        .OrderByIf(true, x => x.Name)
        .GetPage(1, 2)
        .ToList();
    
    Assert.Equal(2, result.Count);
    Assert.Equal(new[] { "Alpha", "Alpha" }, result.Select(x => x.Name).ToArray());
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84586df and d69b800.

📒 Files selected for processing (2)
  • src/NetCore.Utilities.Tests/QueryableExtensionsTests.cs (1 hunks)
  • src/NetCore.Utilities/QueryableExtensions.cs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/NetCore.Utilities.Tests/QueryableExtensionsTests.cs (1)
src/NetCore.Utilities/QueryableExtensions.cs (5)
  • IQueryable (20-30)
  • IQueryable (41-47)
  • IQueryable (58-64)
  • IQueryable (74-80)
  • IQueryable (90-95)
src/NetCore.Utilities/QueryableExtensions.cs (1)
src/NetCore.Utilities.Tests/QueryableExtensionsTests.cs (1)
  • IQueryable (12-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze Code Quality
🔇 Additional comments (2)
src/NetCore.Utilities.Tests/QueryableExtensionsTests.cs (1)

12-27: LGTM!

The test data setup is well-structured with appropriate test entities, including a duplicate name ("Alpha") that effectively tests the DistinctBy functionality.

src/NetCore.Utilities/QueryableExtensions.cs (1)

90-95: Remove the suggestion to use built-in DistinctBy.

This is a utility library that does not depend on EF Core, so it cannot assume the built-in DistinctBy method is available to consumers. The custom implementation using GroupBy().Select(x => x.First()) is appropriate as an extension method on IQueryable<TSource> that works across different LINQ providers and EF Core versions. The current implementation is correct and necessary for a cross-framework utility library.

Likely an incorrect or invalid review comment.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 6, 2025

@mitchelsellers mitchelsellers merged commit 917ff4d into develop Dec 6, 2025
5 checks passed
@mitchelsellers mitchelsellers deleted the feature/iqueryable-extensions branch December 6, 2025 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add IQueryable Extensions to Help EFCore Developers

2 participants