TypedQuery.Abstractions 1.0.3

dotnet add package TypedQuery.Abstractions --version 1.0.3
                    
NuGet\Install-Package TypedQuery.Abstractions -Version 1.0.3
                    
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="TypedQuery.Abstractions" Version="1.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TypedQuery.Abstractions" Version="1.0.3" />
                    
Directory.Packages.props
<PackageReference Include="TypedQuery.Abstractions" />
                    
Project file
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 TypedQuery.Abstractions --version 1.0.3
                    
#r "nuget: TypedQuery.Abstractions, 1.0.3"
                    
#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 TypedQuery.Abstractions@1.0.3
                    
#: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=TypedQuery.Abstractions&version=1.0.3
                    
Install as a Cake Addin
#tool nuget:?package=TypedQuery.Abstractions&version=1.0.3
                    
Install as a Cake Tool

TypedQuery

NuGet NuGet Downloads License

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:

  1. Cold execution (first use)

    • EF Core translates LINQ to SQL
    • SQL template and parameter metadata are cached
  2. 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net6.0

    • No dependencies.
  • net7.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on TypedQuery.Abstractions:

Package Downloads
TypedQuery

TypedQuery - A fluent, type-safe query builder with Dapper execution for .NET. Batch multiple queries into a single database call.

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.

Version Downloads Last Updated
1.0.3 174 12/20/2025
1.0.2 175 12/20/2025
1.0.1 315 12/15/2025
1.0.0 265 12/14/2025