Xpandables.AsyncPaged.Linq
10.0.2
dotnet add package Xpandables.AsyncPaged.Linq --version 10.0.2
NuGet\Install-Package Xpandables.AsyncPaged.Linq -Version 10.0.2
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Xpandables.AsyncPaged.Linq" Version="10.0.2" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Xpandables.AsyncPaged.Linq" Version="10.0.2" />
<PackageReference Include="Xpandables.AsyncPaged.Linq" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Xpandables.AsyncPaged.Linq --version 10.0.2
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Xpandables.AsyncPaged.Linq, 10.0.2"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Xpandables.AsyncPaged.Linq@10.0.2
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Xpandables.AsyncPaged.Linq&version=10.0.2
#tool nuget:?package=Xpandables.AsyncPaged.Linq&version=10.0.2
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
System.AsyncPaged.Linq
LINQ operators for IAsyncPagedEnumerable<T> — filter, project, order, group, join, and materialize paged async sequences.
📖 Overview
System.AsyncPaged.Linq (NuGet: Xpandables.AsyncPaged.Linq) provides C# 14 extension members that bring familiar LINQ operators to IAsyncPagedEnumerable<T>, preserving pagination metadata through transformations. Namespace: System.Linq.
Built for .NET 10 and C# 14.
✨ Extension Categories
| File | Operators |
|---|---|
TransformationExtensions.cs |
SelectManyPaged, SelectPaged, WherePaged, DistinctPaged |
ProjectionExtensions.cs |
SelectPaged<TResult> — element projection |
OrderingExtensions.cs |
OrderByPaged, OrderByDescendingPaged, ThenByPaged |
GroupingExtensions.cs |
GroupByPaged |
JoinExtensions.cs |
JoinPaged, GroupJoinPaged |
SetExtensions.cs |
UnionPaged, IntersectPaged, ExceptPaged, ConcatPaged |
PaginationExtensions.cs |
SkipPaged, TakePaged |
WindowingExtensions.cs |
ChunkPaged, BufferPaged |
MaterializationExtensions.cs |
ToListAsync, ToArrayAsync, ToDictionaryAsync, CountAsync, AnyAsync, FirstOrDefaultAsync |
📦 Installation
dotnet add package Xpandables.AsyncPaged.Linq
Project References: Xpandables.AsyncPaged
🚀 Quick Start
Projection — Transform Elements
using System.Linq;
// Project entities to DTOs, preserving pagination metadata
IAsyncPagedEnumerable<ProductDto> productDtos = pagedProducts
.SelectPaged(p => new ProductDto(p.Id, p.Name, p.Price));
// Project with index
IAsyncPagedEnumerable<RankedProduct> ranked = pagedProducts
.SelectPaged((p, index) => new RankedProduct(index + 1, p.Name));
// Async projection (e.g., call an external service per item)
IAsyncPagedEnumerable<EnrichedProduct> enriched = pagedProducts
.SelectPagedAsync(async p =>
{
decimal discount = await discountService.GetDiscountAsync(p.Id);
return new EnrichedProduct(p.Name, p.Price, discount);
});
Flattening — SelectMany
// Flatten order → order items
IAsyncPagedEnumerable<OrderItem> allItems = pagedOrders
.SelectManyPaged(order => order.Items);
// Flatten with result selector
IAsyncPagedEnumerable<OrderItemDto> itemDtos = pagedOrders
.SelectManyPaged(
order => order.Items,
(order, item) => new OrderItemDto(order.Id, item.ProductName, item.Qty));
Ordering
IAsyncPagedEnumerable<Product> sorted = pagedProducts
.OrderByPaged(p => p.Category)
.ThenByPaged(p => p.Name);
IAsyncPagedEnumerable<Product> sortedDesc = pagedProducts
.OrderByDescendingPaged(p => p.Price);
Grouping
IAsyncPagedEnumerable<IGrouping<string, Product>> grouped = pagedProducts
.GroupByPaged(p => p.Category);
await foreach (var group in grouped)
{
Console.WriteLine($"Category: {group.Key}");
foreach (Product product in group)
Console.WriteLine($" - {product.Name}");
}
Set Operations
IAsyncPagedEnumerable<Product> featured = GetFeaturedProducts();
IAsyncPagedEnumerable<Product> onSale = GetOnSaleProducts();
// Union — combine unique products
IAsyncPagedEnumerable<Product> combined = featured
.UnionPaged(onSale);
// Intersect — products in both sets
IAsyncPagedEnumerable<Product> both = featured
.IntersectPaged(onSale);
// Except — featured but NOT on sale
IAsyncPagedEnumerable<Product> exclusive = featured
.ExceptPaged(onSale);
// Concat — combine with duplicates
IAsyncPagedEnumerable<Product> all = featured
.ConcatPaged(onSale);
Joins
IAsyncPagedEnumerable<OrderSummary> joined = pagedOrders
.JoinPaged(
customers, // inner sequence
order => order.CustomerId, // outer key
customer => customer.Id, // inner key
(order, customer) => new OrderSummary( // result selector
order.Id, customer.Name, order.Total));
Pagination (Skip / Take)
IAsyncPagedEnumerable<Product> page3 = pagedProducts
.SkipPaged(20)
.TakePaged(10);
Windowing (Chunk / Buffer)
// Process in batches of 100
IAsyncPagedEnumerable<Product[]> batches = pagedProducts
.ChunkPaged(100);
await foreach (Product[] batch in batches)
{
await bulkInsertService.InsertAsync(batch);
}
Materialization — Collect Results
// Collect into a List
List<Product> productList = await pagedProducts.ToListAsync(ct);
// Collect into an array
Product[] productArray = await pagedProducts.ToArrayAsync(ct);
// Collect into a dictionary
Dictionary<Guid, Product> productMap = await pagedProducts
.ToDictionaryAsync(p => p.Id, ct);
// Count, Any, First
int count = await pagedProducts.CountAsync(ct);
bool hasAny = await pagedProducts.AnyAsync(ct);
Product? first = await pagedProducts.FirstOrDefaultAsync(ct);
// Pre-compute pagination to avoid double enumeration
IAsyncPagedEnumerable<Product> precomputed = await pagedProducts
.PrecomputePaginationAsync(ct);
// Materialize everything into memory for multiple passes
IAsyncPagedEnumerable<Product> materialized = await pagedProducts
.MaterializeAsync(ct);
Full Pipeline Example
// Build a complete query pipeline for an API endpoint
List<OrderDto> result = await dbContext.Orders
.Where(o => o.Status == "Active")
.OrderByDescending(o => o.CreatedOn)
.Skip(0).Take(50)
.ToAsyncPagedEnumerable()
.SelectPaged(o => new OrderDto(o.Id, o.CustomerName, o.Total, o.CreatedOn))
.ToListAsync(cancellationToken);
📄 License
Apache License 2.0 — Copyright © Kamersoft 2025
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net10.0
- Microsoft.Extensions.Configuration (>= 10.0.5)
- Microsoft.Extensions.Configuration.EnvironmentVariables (>= 10.0.5)
- Microsoft.Extensions.Configuration.Json (>= 10.0.5)
- Microsoft.Extensions.DependencyInjection (>= 10.0.5)
- Microsoft.Extensions.Primitives (>= 10.0.5)
- Xpandables.AsyncPaged (>= 10.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.