TypedQuery 1.0.2
See the version list below for details.
dotnet add package TypedQuery --version 1.0.2
NuGet\Install-Package TypedQuery -Version 1.0.2
<PackageReference Include="TypedQuery" Version="1.0.2" />
<PackageVersion Include="TypedQuery" Version="1.0.2" />
<PackageReference Include="TypedQuery" />
paket add TypedQuery --version 1.0.2
#r "nuget: TypedQuery, 1.0.2"
#:package TypedQuery@1.0.2
#addin nuget:?package=TypedQuery&version=1.0.2
#tool nuget:?package=TypedQuery&version=1.0.2
TypedQuery
A high-performant .NET library for batching multiple database queries into a single roundtrip with type-safe, reusable query definitions.
The Problem
1. EF Core can't run queries concurrently
// 3 sequential roundtrips, no concurrency allowed
var user = await db.Users.FirstOrDefaultAsync(u => u.Id == userId);
var orders = await db.Orders.Where(o => o.UserId == userId).ToListAsync();
var addresses = await db.Addresses.Where(a => a.UserId == userId).ToListAsync();
// Each query waits for the previous one. Database executes them one by one.
2. Dapper's QueryMultipleAsync gets messy
// hard to read, maintain, and reuse
var sql = @"
SELECT * FROM Users WHERE Id = @userId;
SELECT * FROM Orders WHERE UserId = @userId;
SELECT * FROM Addresses WHERE UserId = @userId;";
using var multi = await connection.QueryMultipleAsync(sql, new { userId = 5 });
var user = await multi.ReadFirstOrDefaultAsync<User>();
var orders = (await multi.ReadAsync<Order>()).ToList();
var addresses = (await multi.ReadAsync<Address>()).ToList();
The Solution
TypedQuery batches your queries into a single SQL script.
var result = await db
.ToTypedQuery()
.Add(new GetUserById(userId))
.Add(new GetOrdersByUserId(userId))
.Add(new GetAddressesByUserId(userId))
.ExecuteAsync();
var user = result.Get<UserDto>();
var orders = result.GetList<OrderDto>();
var addresses = result.GetList<AddressDto>();
// One roundtrip.
This drives developers toward cleaner code while improving performance when multiple independent queries are needed together and database roundtrips are expensive.
Installation
dotnet add package TypedQuery
or for EF Core integration ⇒
dotnet add package TypedQuery.EntityFrameworkCore
Quick Start
Define Queries
Raw SQL Query
public class GetUserById(int id) : ITypedQuery<UserDto>
{
public QueryDefinition Build(QueryBuildContext context)
{
return new QueryDefinition(
"SELECT Id, Name, Email FROM Users WHERE Id = @id",
new { id });
}
}
EF Core Query
public class GetOrdersByUserId(int userId) : ITypedQuery<AppDbContext, OrderDto>
{
public IQueryable<OrderDto> Query(AppDbContext db)
{
return db.Orders
.Where(o => o.UserId == userId)
.Select(o => new OrderDto { Id = o.Id, Total = o.Total });
}
}
⚠️ Important: To use EF Core queries, you must register the TypedQuery interceptor:
services.AddDbContext<AppDbContext>(options => { options.UseSqlServer(connectionString); options.UseTypedQuery(); // Required for EF Core mode! });
Execute Queries
With EF Core DbContext
var result = await dbContext
.ToTypedQuery()
.Add(new GetUserById(5))
.Add(new GetOrdersByUserId(5))
.ExecuteAsync();
var user = result.Get<UserDto>();
var orders = result.GetList<OrderDto>();
With Raw DbConnection
var result = await connection
.ToTypedQuery()
.Add(new GetUserById(5))
.Add(new GetActiveProducts())
.ExecuteAsync();
var user = result.Get<UserDto>();
var products = result.GetList<ProductDto>();
Why TypedQuery?
| Feature | Description |
|---|---|
| Single Roundtrip | Multiple queries executed in one database call |
| Type-Safe | Queries and results are strongly typed |
| Reusable | Queries are first-class objects |
| Clean Structure | No manual SQL concatenation |
| SQL Caching | EF Core queries compiled once, reused with Dapper |
| High Performance | Faster than sequential EF Core for multi-query scenarios |
Performance Overview
Local Benchmarks (SQLite in-memory, .NET 8)
| Scenario | Time | Comparison |
|---|---|---|
| EF Core Direct | 71 μs | Baseline |
| TypedQuery EF Core (Warm) | 26 μs | 2.7× faster |
| TypedQuery Raw SQL | 28 μs | 2.5× faster |
| TypedQuery EF Core (Cold) | 808 μs | One-time cost |
| EF Core Sequential (5 queries) | 373 μs | Baseline |
| TypedQuery Batched (5 queries) | 132 μs | 2.8× faster |
Execution Model
TypedQuery uses a dual-mode execution strategy:
Cold execution (first use)
- EF Core translates LINQ to SQL
- SQL template and parameter metadata are cached
Warm execution (subsequent uses)
- EF Core is skipped
- Cached SQL is executed via Dapper
Implications:
- Cold cost is paid once per query type
- Warm execution is significantly faster and allocates less memory
Packages
| Package | Description |
|---|---|
| TypedQuery.Abstractions | Core interfaces |
| TypedQuery | Query execution engine |
| TypedQuery.EntityFrameworkCore | EF Core integration and SQL caching |
Contributing
Contributions are welcome! This library is in active development.
Acknowledgments
- Built on top of Dapper for query execution
- Inspired by the need for cleaner batch query patterns in .NET
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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. |
-
net10.0
- Dapper (>= 2.0.4 && < 3.0.0)
- TypedQuery.Abstractions (>= 1.0.2)
-
net6.0
- Dapper (>= 2.0.4 && < 3.0.0)
- TypedQuery.Abstractions (>= 1.0.2)
-
net7.0
- Dapper (>= 2.0.4 && < 3.0.0)
- TypedQuery.Abstractions (>= 1.0.2)
-
net8.0
- Dapper (>= 2.0.4 && < 3.0.0)
- TypedQuery.Abstractions (>= 1.0.2)
-
net9.0
- Dapper (>= 2.0.4 && < 3.0.0)
- TypedQuery.Abstractions (>= 1.0.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on TypedQuery:
| Package | Downloads |
|---|---|
|
TypedQuery.EntityFrameworkCore
Entity Framework Core integration for TypedQuery - Build type-safe LINQ queries and batch them with raw SQL in a single database call |
GitHub repositories
This package is not used by any popular GitHub repositories.