The below code works fine (throws no translation error):
string text = "someString";
string refId = "refId";
bool forward = true;
IQueryable<Tin> q = queryable.Where(o => forward ? text.IsGreaterThan(refId) : text.IsLessThan(refId));
var x = await q.ToArrayAsync();
IsGreaterThan()
and IsLessThan()
are methods that have been registered in OnModelCreating(ModelBuilder builder)
from dbContext, as explained in this answer. So the problem is not with those methods.
The below code doesn't work:
string refId = "refId";
Expression<Func<Tin, string>> key = obj => obj.Id;
bool forward = true;
IQueryable<Tin> q = queryable.Where(o => forward ? key.Compile()(o).IsGreaterThan(refId) : key.Compile()(o).IsLessThan(refId));
var x = await q.ToArrayAsync();
It throws the below error.
System.InvalidOperationException: The LINQ expression 'DbSet<Follow>
.Where(f => f.FollowerId == __userId_0)
.Where(f => Invoke(__Compile_1, f[Follow])
.IsGreaterThan(__refId_2))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync().
I understand why it fails. Expression<Func<>>.Compile()
returns a Func<>
and those cannot be used in Linq to Sql. So I've been looking for workarounds.
The most promising I found is from this answer. It worked as expected in the fiddle he provided, but for some reason, it didn't work for me. My code after implementing his answer:
string refId = "refId";
Expression<Func<Tin, string>> key = obj => obj.Id;
bool forward = true;
Func<Tin, string> keyFunc = key.Compile();
Expression<Func<Tin, bool>> where = o => forward ? keyFunc(o).IsGreaterThan(refId) : keyFunc(o).IsLessThan(refId);
where.Replace(() => keyFunc, key);
IQueryable<Tin> q = queryable.Where(where);
var x = await q.ToArrayAsync();
Is there some other way to nest Expression<Func<>>
s?
EDIT: As mentioned by @pinkfloydx33:
where.Replace(() => keyFunc, key);
should have been:
where = where.Replace(() => keyFunc, key);
Funny enough, I make this same mistake with string.Replace()
a loooot.
It works fine now after this.