Skip to content

ExpressiveSharpModern C# syntax in LINQ expression trees

Write null-conditional operators, switch expressions, and pattern matching in your queries β€” source-generated at compile time with zero runtime overhead.

At a Glance ​

Without ExpressiveSharp β€” you hit two walls immediately:

csharp
// Problem 1: Computed properties are opaque to EF Core
public class Order
{
    public double Price { get; set; }
    public int Quantity { get; set; }
    public Customer? Customer { get; set; }

    // EF Core can't see inside this β€” it throws or silently fetches everything
    public double Total => Price * Quantity;
}

// Problem 2: Modern C# syntax is illegal in expression trees
db.Orders
    .Where(o => o.Customer?.Email != null)       // CS8072: ?. not allowed
    .Select(o => new { Grade = o.Price switch {  // CS8514: switch not allowed
        >= 100 => "Premium",
        _ => "Budget"
    }});

You end up duplicating formulas as inline expressions and writing ugly ternary chains.

With ExpressiveSharp β€” write natural C#, the source generator handles the rest:

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

    [Expressive]
    public double Total => Price * Quantity;      // translated to SQL

    [Expressive]
    public string GetGrade() => Price switch      // switch expression -> SQL CASE
    {
        >= 100 => "Premium",
        >= 50  => "Standard",
        _      => "Budget",
    };
}

// Extension methods and C# 14 extension properties work too
public static class OrderExtensions
{
    [Expressive]
    public static bool IsHighValue(this Order o) => o.Total > 500;
}

// C# 14 extension members (.NET 10+)
public static class OrderReviewExtensions
{
    extension(Order o)
    {
        [Expressive]
        public bool NeedsReview => o.Customer?.Email == null && o.Total > 100;
    }
}

// ?. syntax, computed properties, switch expressions β€” all translated to SQL
var results = db.Orders
    .AsExpressiveDbSet()
    .Where(o => o.Customer?.Email != null && o.IsHighValue())
    .Select(o => new { o.Id, o.Total, Grade = o.GetGrade(), o.NeedsReview })
    .ToList();
sql
SELECT "o"."Id",
       "o"."Price" * CAST("o"."Quantity" AS REAL) AS "Total",
       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

Computed properties are inlined into SQL β€” no client-side evaluation, no N+1. Modern syntax just works.

NuGet Packages ​

PackageDescription
ExpressiveSharpCore runtime β€” [Expressive] attribute, expression expansion, transformers
ExpressiveSharp.EntityFrameworkCoreEF Core integration β€” UseExpressives(), ExpressiveDbSet<T>, Include/ThenInclude, async methods
ExpressiveSharp.EntityFrameworkCore.RelationalExtensionsSQL window functions β€” ROW_NUMBER, RANK, DENSE_RANK, NTILE (experimental)

Released under the MIT License.