ExpressiveSharp.EntityFrameworkCore 0.2.1

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

ExpressiveSharp

CI codecov NuGet NuGet Downloads License: MIT .NET GitHub Stars GitHub Issues

Documentation | Getting Started

Source generator that enables modern C# syntax in LINQ expression trees. All expression trees are generated at compile time with minimal runtime overhead.

The Problem

There are two problems when using C# with LINQ providers like EF Core:

1. Expression tree syntax restrictions. You write a perfectly reasonable query and hit:

error CS8072: An expression tree lambda may not contain a null propagating operator

Expression trees (Expression<Func<...>>) only support a restricted subset of C# — no ?., no switch expressions, no pattern matching. So you end up writing ugly ternary chains instead of the clean code you'd write anywhere else. (Why hasn't this been fixed?)

2. Computed properties are opaque to LINQ providers. You define public string FullName => FirstName + " " + LastName and use it in a query — but EF Core can't see inside the property getter. It either throws a runtime translation error, or worse, silently fetches the entire entity to evaluate FullName on the client (overfetching). The only workaround is to duplicate the logic as an inline expression in every query that needs it.

ExpressiveSharp fixes this. Write natural C# and the source generator builds the expression tree at compile time:

public class Order
{
    public int Id { get; set; }
    public double Price { get; set; }
    public int Quantity { get; set; }
    public Customer? Customer { get; set; }

    // Computed property — reusable in any query, translated to SQL
    [Expressive]
    public double Total => Price * Quantity;

    // Switch expression — normally illegal in expression trees
    [Expressive]
    public string GetGrade() => Price switch
    {
        >= 100 => "Premium",
        >= 50  => "Standard",
        _      => "Budget",
    };
}

// [Expressive] members + ?. syntax — all translated to SQL
var results = db.Orders
    .AsExpressiveDbSet()
    .Where(o => o.Customer?.Email != null)
    .Select(o => new { o.Id, o.Total, Email = o.Customer?.Email, Grade = o.GetGrade() })
    .ToList();

Generated SQL (SQLite — other providers produce equivalent dialect-specific SQL):

SELECT "o"."Id",
       "o"."Price" * CAST("o"."Quantity" AS REAL) AS "Total",
       "c"."Email",
       CASE
           WHEN "o"."Price" >= 100.0 THEN 'Premium'
           WHEN "o"."Price" >= 50.0 THEN 'Standard'
           ELSE 'Budget'
       END AS "Grade"
FROM "Orders" AS "o"
LEFT JOIN "Customers" AS "c" ON "o"."CustomerId" = "c"."Id"
WHERE "c"."Email" IS NOT NULL

Quick Start

dotnet add package ExpressiveSharp
# Optional: EF Core integration
dotnet add package ExpressiveSharp.EntityFrameworkCore

See the BasicSample and EFCoreSample projects for runnable examples.

Which API Should I Use?

Mark computed properties and methods with [Expressive] to generate companion expression trees. Then choose how to wire them into your queries:

Scenario API
EF Core — modern syntax + [Expressive] expansion on DbSet ExpressiveDbSet<T>
Any IQueryable — modern syntax + [Expressive] expansion .WithExpressionRewrite()
EF Core — SQL window functions (ROW_NUMBER, RANK, etc.) WindowFunction.*
Advanced — build an Expression<T> inline, no attribute needed ExpressionPolyfill.Create
Advanced — expand [Expressive] members in an existing expression tree .ExpandExpressives()
Advanced — make third-party/BCL members expressable [ExpressiveFor]

Features

Category Examples
Null-conditional operators ?. member access and indexer
Switch expressions With relational, logical, type, and property patterns
Pattern matching Constant, type, relational, logical, property, positional, list patterns
String interpolation Converted to string.Concat
Constructor projections [Expressive] constructors for DTO projections with inheritance support
Block bodies (opt-in) if/else, switch statements, foreach/for loops, local variables
External member mapping [ExpressiveFor] for BCL/third-party members
Tuples, index/range, with, collection expressions And more modern C# syntax
Expression transformers Built-in + custom IExpressionTreeTransformer pipeline
SQL window functions ROW_NUMBER, RANK, DENSE_RANK, NTILE (experimental)

See the full documentation for detailed usage, reference, and recipes.

Contributing

dotnet build    # Build all projects
dotnet test     # Run all tests

License

MIT

Product Compatible and additional computed target framework versions.
.NET 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.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on ExpressiveSharp.EntityFrameworkCore:

Package Downloads
ExpressiveSharp.EntityFrameworkCore.RelationalExtensions

Experimental relational database extensions for ExpressiveSharp EF Core — window functions (ROW_NUMBER, RANK, DENSE_RANK, NTILE) and indexed Select. Note: EF Core has an open issue (dotnet/efcore#12747) for native window function support; this package may be superseded when that ships.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.1 0 3/31/2026
0.2.0 36 3/30/2026
0.1.0 39 3/25/2026