Just Add [Expressive]
Decorate any property, method, or constructor with [Expressive] and the source generator does the rest β no boilerplate, no manual expression trees.
Write null-conditional operators, switch expressions, and pattern matching in your queries β source-generated at compile time with zero runtime overhead.
Without ExpressiveSharp β you hit two walls immediately:
// 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:
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();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 NULLComputed properties are inlined into SQL β no client-side evaluation, no N+1. Modern syntax just works.
| Package | Description |
|---|---|
ExpressiveSharp | Core runtime β [Expressive] attribute, expression expansion, transformers |
ExpressiveSharp.EntityFrameworkCore | EF Core integration β UseExpressives(), ExpressiveDbSet<T>, Include/ThenInclude, async methods |
ExpressiveSharp.EntityFrameworkCore.RelationalExtensions | SQL window functions β ROW_NUMBER, RANK, DENSE_RANK, NTILE (experimental) |