Use extension methods in Entity Framework Core queries
Install these two nuget packages:
Clave.Expressionify
Clave.Expressionify.Tasks
- Mark the
public static
extension method with the[Expressionify]
attribute. - Call
.Expressionify()
in your Entity Framework query chain, before using any extension method. - Use the extension method in the query
Lets say you have this code:
var users = await db.Users
.Where(user => user.DateOfBirth < DateTime.Now.AddYears(-18))
.ToListAsync();
That second line is a bit long, so it would be nice to pull it out as a reusable extension method:
public static Extensions
{
public static bool IsOver18(this User user)
=> user.DateOfBirth < DateTime.Now.AddYears(-18);
}
// ...
var users = await db.Users
.Where(user => user.IsOver18())
.ToListAsync();
Unfortunately this forces Entity Framework to run the query in memory, rather than in the database. That's not very efficient...
But, with just two additional lines of code we can get Entity Framework to understand how translate our extension method to SQL
public static Extensions
{
+ [Expressionify]
public static bool IsOver18(this User user)
=> user.DateOfBirth < DateTime.Now.AddYears(-18);
}
// ...
// create a query
var users = await db.Users
+ .Expressionify()
.Where(user => user.IsOver18())
.ToListAsync();
Expressionify uses the Roslyn code analyzer and generator to look for public
static
methods with expression bodies tagged with the [Expressionify]
attribute.
// ✔ OK
[Expressionify]
public static int ToInt(this string value) => Convert.ToInt32(value);
// ❌ Not ok (it's not static)
[Expressionify]
public int ToInt(this string value) => Convert.ToInt32(value);
// ❌ Not ok (it's missing the attribute)
public static int ToInt(this string value) => Convert.ToInt32(value);
// ❌ Not ok (it's not public)
[Expressionify]
private static int ToInt(this string value) => Convert.ToInt32(value);
// ❌ Not ok (it doesn't have an expression body)
[Expressionify]
public static int ToInt(this string value)
{
return Convert.ToInt32(value);
}
The first part of this project relies heavily on the work done by Luke McGregor in his LinqExpander project, as described in his article on composable repositories - nesting expressions, and on the updated code by Ben Cull in his article Expression and Projection Magic for Entity Framework Core .
The second part of this project uses Roslyn to analyze and generate code, and part of it is built directly on code by Carlos Mendible from his article Create a class with .NET Core and Roslyn.
The rest is stitched together from various Stack Overflow answers and code snippets found on GitHub.