0

I have a specific Expression that is dynamically generated that I want to reuse in a Select statement that ultimately will be execute by EF Core as SQL in Postgres. So I am of course limited to creating expressions in a way that can be translated to SQL.

Let's call the EF Core entity in the database Thing, it has a property Id and I have a method GeneratePermissionsExpressionthat generates an expression of the type Expression<Func<Thing, bool>>. This is essentially a kind of permissions check, you pass it a Thing and it gives back true or false.

I'm using this expression in a different place, and now I want to reuse it here to generate a List of {Id, HasPermission} objects, each element of the list representing this permissions check for one Thing. I can use my existing expression without issue to just generate a list of bools representing the permissions check, but in this case I also need the corresponding Ids.

What I've done so far only requires some lambda literals and the right types, but now it looks like I have to manipulate and generate Expression trees and that is a lot more complex. I tried a few things, including using Expression.Invoke, but I didn't get anywhere with that. I managed to generate an Expression representing the function "(Id, HasPermission) => new PermissionsIdResult() {Id = Id, HasPermission = HasPermission}", but failed when trying to use that to achieve my goal, and I suspect I was on entirely the wrong path there.

The code that works and only produces a list of bools looks like the following, ids in this case is a List of ints, GeneratePermissionsExpression is the method that returns my Expression<Func<Thing, bool>>:

 var query = context.Things
   .Where(t => ids.Contains(t.Id))
   .Select(GeneratePermissionsExpression());

This query is then executed with ToListAsync() by EF Core.

What I now want to do looks more like the following, but obviously that code doesn't work nor compile:

var query = context.Things
   .Where(t => ids.Contains(t.Id))
   .Select( new ResultClass{Id = t.Id, HasPermission = GeneratePermissionsExpression());

ResultClass is simply a class containing the {Id, HasPermission} properties, I wanted to avoid dealing with anonymous classes here. Now what the part where I write

HasPermission = GeneratePermissionsExpression()

should do is to use the Expression that method returns to fill out the HasPermission property on my ResultClass object. I tried using Invoke here, but then I get InvocationExpressions I can't run with EF Core against the database.

How can I use my Expression<Func<Thing, bool>> to fill out the HasPermission property on that object and have all that executed in the database in the end?

Fabian
  • 439
  • 3
  • 9
  • Check this [my answer](https://stackoverflow.com/a/66386142/10646316) – Svyatoslav Danyliv Jun 06 '23 at 18:04
  • @SvyatoslavDanyliv Is the only way to do this to use a library? And I don't really get why this should require decompiling as I already have my function as an Expression. – Fabian Jun 06 '23 at 21:10
  • You can use LINKQKit and it's `Expandable` attribute. Or use LINQKit's `Invoke` extension. Anyway without additional Expression Tree preparation it will not work - it is what these libraries do. – Svyatoslav Danyliv Jun 07 '23 at 08:16

0 Answers0