Skip to content

Conversation

@a-gubskiy
Copy link
Member

@a-gubskiy a-gubskiy commented Aug 18, 2025

This pull request introduces a new Entity Framework 6 extension for the X.PagedList library and updates the solution structure to support it. The main changes include adding the X.PagedList.EntityFramework project, updating build and versioning information, and ensuring compatibility with .NET Framework 4.8.1. The solution file format is also updated for improved organization.

New Entity Framework 6 extension

  • Added new project X.PagedList.EntityFramework providing extension methods for paged queries in EF6, including asynchronous paging support via PagedListExtensions.cs. [1] [2]
  • Added documentation for X.PagedList.EntityFramework in README.md, describing its purpose and usage.

Solution and project structure updates

  • Replaced the legacy Visual Studio solution file (X.PagedList.sln) with a new XML-based solution file (X.PagedList.slnx) that organizes projects into /src/, /tests/, and /examples/ folders. [1] [2]

Build and compatibility improvements

  • Updated src/Directory.Build.props to increment version numbers to 10.5.7.
  • Updated X.PagedList project to include .NET Framework 4.8.1 as a target framework, ensuring compatibility with EF6.

Summary by CodeRabbit

  • New Features

    • Added async pagination support for Entity Framework 6, enabling creation of paged lists from IQueryable with optional cancellation and optimized total count handling.
  • Documentation

    • Introduced README for the EF6 extensions with overview, usage pointers, and links to further resources.
  • Chores

    • Bumped package version to 10.5.9.
    • Updated solution structure and format to improve project organization (no runtime or API changes).

danm-de and others added 6 commits October 23, 2024 14:57
@coderabbitai
Copy link

coderabbitai bot commented Aug 18, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Caution

Review failed

The pull request is closed.

Walkthrough

Replaced the legacy .sln with a new XML-based .slnx solution, bumped version metadata to 10.5.9, and introduced an EF6-focused project with async IQueryable pagination extensions, accompanying project file, and README. No other code paths were modified.

Changes

Cohort / File(s) Summary
Solution management
X.PagedList.sln, X.PagedList.slnx
Removed legacy .sln and added XML-based .slnx aggregating projects under /examples, /src, and /tests.
Build/version metadata
src/Directory.Build.props
Incremented Version, AssemblyVersion, FileVersion, and PackageVersion from 10.5.8 to 10.5.9.
EF6 extension library
src/X.PagedList.EntityFramework/PagedListExtensions.cs, src/X.PagedList.EntityFramework/X.PagedList.EntityFramework.csproj, src/X.PagedList.EntityFramework/README.md
Added EF6 async IQueryable pagination extensions (ToPagedListAsync), new project targeting net481/netstandard2.1 with EF6 dependency, and README; includes packaging of README and LICENSE.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant IQueryable as IQueryable<T>
  participant EF as EF Provider
  participant DB as Database
  participant PagedList as X.PagedList

  Caller->>IQueryable: ToPagedListAsync(pageNumber, pageSize, totalSetCount?, ct)
  IQueryable->>EF: CountAsync(ct) [if totalSetCount not provided]
  EF->>DB: COUNT(*)
  DB-->>EF: totalCount
  EF-->>IQueryable: totalCount
  IQueryable->>EF: Skip/Take query ToListAsync(ct) [if totalCount > 0]
  EF->>DB: SELECT page rows
  DB-->>EF: subset rows
  EF-->>IQueryable: List<T> subset
  IQueryable-->>Caller: subset, totalCount
  Caller->>PagedList: new StaticPagedList<T>(subset, pageNumber, pageSize, totalCount)
  PagedList-->>Caller: IPagedList<T>
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

I nibble through pages, hop through rows,
Counting carrots the query throws.
Skip, take, crunch—so neat, so fine,
A paged buffet on EF vine.
Version bumped, new warren spun—
.slnx shines; my sprint is done. 🥕✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3c203bb and 4c12488.

📒 Files selected for processing (3)
  • src/Directory.Build.props (1 hunks)
  • src/X.PagedList.EntityFramework/PagedListExtensions.cs (1 hunks)
  • src/X.PagedList.EntityFramework/X.PagedList.EntityFramework.csproj (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 1

🧹 Nitpick comments (10)
src/X.PagedList.EntityFramework/README.md (1)

13-17: Tighten wording and add a short “EF6 is legacy” note

  • Small grammar tweak.
  • Since the PR positions EF6 as deprecated/legacy, add a brief note to set expectations and point EF Core users to the alternative.

Suggested edits:

-You can find all information about how to use X.PagedList libraries in [Wiki](https://github.com/dncuug/X.PagedList/wiki)
+You can find all information about how to use X.PagedList libraries in the [Wiki](https://github.com/dncuug/X.PagedList/wiki)
+
+> Note: Entity Framework 6 is legacy/deprecated. This package exists for maintenance and compatibility with EF6 apps.  
+> For EF Core, use the X.PagedList.EF (EF Core) extensions instead.
src/X.PagedList.EntityFramework/X.PagedList.EntityFramework.csproj (1)

3-9: Consider silencing EF6 deprecation warning locally (optional)

EF6 NuGet may emit NU1903 (deprecated). If your CI treats warnings as errors (now or in the future), builds can break. It’s reasonable to suppress this warning in this EF6-only project.

Optional addition:

   <PropertyGroup>
     <Title>X.PagedList.EntityFramework</Title>
     <Description>Entity Framework 6 (legacy) extensions for X.PagedList library</Description>
     <LangVersion>default</LangVersion>
     <TargetFrameworks>net481;netstandard2.1</TargetFrameworks>
     <PackageTags>paging pagedlist paged list entity framework ef6</PackageTags>
+    <NoWarn>$(NoWarn);NU1903</NoWarn>
   </PropertyGroup>
src/X.PagedList.EntityFramework/PagedListExtensions.cs (8)

39-47: Prefer ArgumentOutOfRangeException overloads with paramName and actual value

Passing only a message omits param metadata. Use the overloads that include paramName and actual value for better diagnostics.

Apply this diff:

-            throw new ArgumentOutOfRangeException($"pageNumber = {pageNumber}. PageNumber cannot be below 1.");
+            throw new ArgumentOutOfRangeException(nameof(pageNumber), pageNumber, "PageNumber must be greater than or equal to 1.");

-            throw new ArgumentOutOfRangeException($"pageSize = {pageSize}. PageSize cannot be less than 1.");
+            throw new ArgumentOutOfRangeException(nameof(pageSize), pageSize, "PageSize must be greater than or equal to 1.");

52-56: Validate provided total count is non-negative

If callers pass a negative totalSetCount, you’ll propagate an invalid count into StaticPagedList metadata. Guard against this.

-        if (totalSetCount.HasValue)
-        {
-            totalCount = totalSetCount.Value;
-        }
+        if (totalSetCount.HasValue)
+        {
+            if (totalSetCount.Value < 0)
+                throw new ArgumentOutOfRangeException(nameof(totalSetCount), totalSetCount, "Total item count cannot be negative.");
+            totalCount = totalSetCount.Value;
+        }

63-76: Avoid round-trip when page is beyond range; use Array.Empty for empty subset

When skip >= totalCount, a Skip/Take call does an unnecessary DB query. Also, prefer Array.Empty() for the empty case to avoid a list allocation.

-        if (totalCount > 0)
-        {
-            int skip = (pageNumber - 1) * pageSize;
-
-            subset = await superset
-                .Skip(skip)
-                .Take(pageSize)
-                .ToListAsync(cancellationToken)
-                .ConfigureAwait(false);
-        }
-        else
-        {
-            subset = new List<T>();
-        }
+        int skip = (pageNumber - 1) * pageSize;
+        if (totalCount <= 0 || skip >= totalCount)
+        {
+            subset = Array.Empty<T>();
+        }
+        else
+        {
+            subset = await superset
+                .Skip(skip)
+                .Take(pageSize)
+                .ToListAsync(cancellationToken)
+                .ConfigureAwait(false);
+        }

11-16: Fix XML doc to reference the actual public surface

Docs say PagedList but this API returns IPagedList backed by StaticPagedList. Also minor wording.

-/// EntityFramework extension methods designed to simplify the creation of instances of <see cref="PagedList{T}"/>.
+/// Entity Framework 6 extension methods that help create instances of <see cref="IPagedList{T}"/> (backed by <see cref="StaticPagedList{T}"/>).

22-27: Tighten parameter XML docs and fill missing cancellation token description

Clarify that the source must be an EF6 IQueryable and recommend explicit ordering; add a description for cancellationToken.

-/// <param name="superset">The collection of objects to be divided into subsets. If the collection implements <see cref="IQueryable{T}"/>, it will be treated as such.</param>
+/// <param name="superset">The EF6 <see cref="IQueryable{T}"/> query to page. Ensure a deterministic ordering (e.g., via <c>OrderBy</c>) for stable paging.</param>
 /// <param name="pageNumber">The one-based index of the subset of objects to be contained by this instance.</param>
 /// <param name="pageSize">The maximum size of any individual subset.</param>
-/// <param name="totalSetCount">The total size of set</param>
-/// <param name="cancellationToken"></param>
+/// <param name="totalSetCount">Optional total item count for the full set, when known. If omitted, a <c>CountAsync</c> query will be executed.</param>
+/// <param name="cancellationToken">Cancellation token to cancel the underlying database operations.</param>

31-32: Update see-also to match usage/return types

The implementation returns StaticPagedList as IPagedList; update the reference accordingly.

-/// <seealso cref="PagedList{T}"/>
+/// <seealso cref="StaticPagedList{T}"/>

25-25: Consider renaming totalSetCount to totalItemCount for consistency with X.PagedList terminology

X.PagedList commonly uses “totalItemCount.” Since this is a new public API, aligning now avoids future breaking changes.

-/// <param name="totalSetCount">Optional total item count for the full set, when known. If omitted, a <c>CountAsync</c> query will be executed.</param>
+/// <param name="totalItemCount">Optional total item count for the full set, when known. If omitted, a <c>CountAsync</c> query will be executed.</param>
@@
-    public static async Task<IPagedList<T>> ToPagedListAsync<T>(this IQueryable<T> superset, int pageNumber, int pageSize, int? totalSetCount, CancellationToken cancellationToken)
+    public static async Task<IPagedList<T>> ToPagedListAsync<T>(this IQueryable<T> superset, int pageNumber, int pageSize, int? totalItemCount, CancellationToken cancellationToken)
@@
-        if (totalSetCount.HasValue)
+        if (totalItemCount.HasValue)
         {
-            if (totalSetCount.Value < 0)
-                throw new ArgumentOutOfRangeException(nameof(totalSetCount), totalSetCount, "Total item count cannot be negative.");
-            totalCount = totalSetCount.Value;
+            if (totalItemCount.Value < 0)
+                throw new ArgumentOutOfRangeException(nameof(totalItemCount), totalItemCount, "Total item count cannot be negative.");
+            totalCount = totalItemCount.Value;
         }
@@
-/// <param name="totalSetCount">The total size of set</param>
+/// <param name="totalItemCount">The total number of items in the full set.</param>
@@
-    public static Task<IPagedList<T>> ToPagedListAsync<T>(this IQueryable<T> superset, int pageNumber, int pageSize, int? totalSetCount = null)
+    public static Task<IPagedList<T>> ToPagedListAsync<T>(this IQueryable<T> superset, int pageNumber, int pageSize, int? totalItemCount = null)
     {
-        return ToPagedListAsync(superset, pageNumber, pageSize, totalSetCount, CancellationToken.None);
+        return ToPagedListAsync(superset, pageNumber, pageSize, totalItemCount, CancellationToken.None);
     }

Also applies to: 32-32, 52-56, 89-89, 95-97


67-71: Reminder: ensure upstream queries apply ordering before Skip/Take

EF does not guarantee ordering unless specified. Without OrderBy, paging is nondeterministic. Consider documenting this in README and examples for this new package.

I can open a follow-up PR to update README.md with an ordering note and example if you’d like.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4bb39c1 and 3c203bb.

📒 Files selected for processing (7)
  • X.PagedList.sln (0 hunks)
  • X.PagedList.slnx (1 hunks)
  • src/Directory.Build.props (1 hunks)
  • src/X.PagedList.EntityFramework/PagedListExtensions.cs (1 hunks)
  • src/X.PagedList.EntityFramework/README.md (1 hunks)
  • src/X.PagedList.EntityFramework/X.PagedList.EntityFramework.csproj (1 hunks)
  • src/X.PagedList/X.PagedList.csproj (1 hunks)
💤 Files with no reviewable changes (1)
  • X.PagedList.sln
⏰ 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 (csharp)
🔇 Additional comments (8)
src/Directory.Build.props (1)

13-16: Version bump to 10.5.7 looks consistent and scoped correctly

All four version fields are aligned. No issues spotted.

src/X.PagedList/X.PagedList.csproj (1)

8-8: Add net481 target — LGTM

The expanded TFM set aligns with EF6 compatibility requirements. No other changes needed.

src/X.PagedList.EntityFramework/X.PagedList.EntityFramework.csproj (2)

20-21: Dependency choice and range look correct

  • EF pinned to [6.5.1,7.0.0) ensures latest EF6 without accidentally flowing into EF Core.
  • JetBrains.Annotations is private — good.

No changes requested.


25-25: EF6 async extensions verified

  • src/X.PagedList.EntityFramework/PagedListExtensions.cs includes using System.Data.Entity;
  • Uses await superset.CountAsync(cancellationToken).ConfigureAwait(false)
  • Uses await superset.Skip(skip).Take(pageSize).ToListAsync(cancellationToken).ConfigureAwait(false)

All EF6 async methods are correctly used.

X.PagedList.slnx (1)

1-16: No CI/docs references to .sln – .slnx-only solution is safe
A search across all YAML, XML, Markdown and shell scripts for “.sln” or dotnet build *.sln returned no hits. There are no CI workflows or docs depending on an old .sln, so you can proceed with the .slnx file alone.
Optional: if you have contributors who rely on Visual Studio’s classic solution format, you may still include a legacy .sln or document how to open the .slnx.

src/X.PagedList.EntityFramework/PagedListExtensions.cs (3)

32-79: EF6 async paging implementation is solid

CountAsync/ToListAsync with ConfigureAwait(false), null/arg validation, and returning StaticPagedList look correct. This should integrate well with EF6.


58-61: Good use of ConfigureAwait(false) in library code

Using ConfigureAwait(false) on EF6 async calls is the right choice for a library.

Also applies to: 70-71


9-9: File-scoped namespace is supported under your SDK-style setup

I’ve confirmed that X.PagedList.EntityFramework.csproj is an SDK-style project with <LangVersion>default</LangVersion>. When built with the .NET SDK (v6+), “default” maps to C# 10+, so file-scoped namespaces will compile as expected. No changes needed here.

Comment on lines +1 to +5
# X.Extensions.PagedList.EF6

[![NuGet Version](http://img.shields.io/nuget/v/X.PagedList.EntityFramework.svg?style=flat)](https://www.nuget.org/packages/X.PagedList.EntityFramework/)
[![Twitter URL](https://img.shields.io/twitter/url/https/x.com/andrew_gubskiy.svg?style=social&label=Follow%20me!)](https://x.com/intent/user?screen_name=andrew_gubskiy)

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix package name in title and use HTTPS for badges

  • Title says “X.Extensions.PagedList.EF6” but the project/package is X.PagedList.EntityFramework. This will confuse users.
  • The NuGet badge uses http; prefer https to avoid mixed-content warnings.

Apply:

-# X.Extensions.PagedList.EF6
+# X.PagedList.EntityFramework (EF6)

-[![NuGet Version](http://img.shields.io/nuget/v/X.PagedList.EntityFramework.svg?style=flat)](https://www.nuget.org/packages/X.PagedList.EntityFramework/)
+[![NuGet Version](https://img.shields.io/nuget/v/X.PagedList.EntityFramework.svg?style=flat)](https://www.nuget.org/packages/X.PagedList.EntityFramework/)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# X.Extensions.PagedList.EF6
[![NuGet Version](http://img.shields.io/nuget/v/X.PagedList.EntityFramework.svg?style=flat)](https://www.nuget.org/packages/X.PagedList.EntityFramework/)
[![Twitter URL](https://img.shields.io/twitter/url/https/x.com/andrew_gubskiy.svg?style=social&label=Follow%20me!)](https://x.com/intent/user?screen_name=andrew_gubskiy)
# X.PagedList.EntityFramework (EF6)
[![NuGet Version](https://img.shields.io/nuget/v/X.PagedList.EntityFramework.svg?style=flat)](https://www.nuget.org/packages/X.PagedList.EntityFramework/)
[![Twitter URL](https://img.shields.io/twitter/url/https/x.com/andrew_gubskiy.svg?style=social&label=Follow%20me!)](https://x.com/intent/user?screen_name=andrew_gubskiy)
🤖 Prompt for AI Agents
In src/X.PagedList.EntityFramework/README.md around lines 1 to 5, the README
title incorrectly says "X.Extensions.PagedList.EF6" and the NuGet badge uses an
http URL; change the title to "X.PagedList.EntityFramework" to match the
project/package name and update the NuGet badge URL to use https
(https://img.shields.io/nuget/v/X.PagedList.EntityFramework.svg?style=flat) so
badges are served securely.

Added JetBrains.Annotations as a package reference to all projects. Updated Entity Framework Core version for net8.0 target in X.PagedList.EF and expanded net7.0 support. Minor formatting improvements in project files.
Update package version
@a-gubskiy a-gubskiy requested a review from Copilot August 18, 2025 09:06
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This pull request introduces a new Entity Framework 6 extension library for X.PagedList and modernizes the solution structure. The main purpose is to provide EF6-specific async pagination functionality while maintaining compatibility with legacy .NET Framework applications.

  • Adds a new X.PagedList.EntityFramework project with async pagination extensions for EF6
  • Migrates from traditional .sln to XML-based .slnx solution format for better organization
  • Updates version numbers across the solution to 10.5.9

Reviewed Changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/X.PagedList.EntityFramework/X.PagedList.EntityFramework.csproj New project file targeting .NET Framework 4.8.1 and .NET Standard 2.1 with EF6 dependencies
src/X.PagedList.EntityFramework/README.md Documentation for the new EF6 extension library
src/X.PagedList.EntityFramework/PagedListExtensions.cs Core extension methods providing async pagination for IQueryable with EF6
src/Directory.Build.props Version bump from 10.5.8 to 10.5.9 for assembly, file, and package versions
X.PagedList.slnx New XML-based solution file replacing the traditional .sln format

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@a-gubskiy a-gubskiy merged commit 4a9c349 into master Aug 18, 2025
3 of 4 checks passed
@a-gubskiy a-gubskiy deleted the dev branch August 18, 2025 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants