Skip to content

Commit 88848a0

Browse files
committed
Generate expressions to use sql parameters instead of constants
This is so that the DE/EF can reuse the same query plan.
1 parent 7e7585d commit 88848a0

File tree

1 file changed

+16
-14
lines changed

1 file changed

+16
-14
lines changed

src/MR.EntityFrameworkCore.KeysetPagination/KeysetPaginationExtensions.cs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ private static Expression<Func<T, bool>> BuildKeysetFilterPredicateExpression<T>
254254
var referenceValues = GetValues(items, reference);
255255

256256
var firstMemberAccessExpression = default(MemberExpression);
257-
var firstReferenceValueExpression = default(ConstantExpression);
257+
var firstReferenceValueExpression = default(Expression);
258258

259259
// entity =>
260260
var param = Expression.Parameter(typeof(T), "entity");
@@ -273,7 +273,9 @@ private static Expression<Func<T, bool>> BuildKeysetFilterPredicateExpression<T>
273273
var isInnerLastOperation = j + 1 == innerLimit;
274274
var item = items[j];
275275
var memberAccess = Expression.MakeMemberAccess(param, item.Property);
276-
var referenceValueExpression = Expression.Constant(referenceValues[j]);
276+
var referenceValue = referenceValues[j];
277+
Expression<Func<object>> referenceValueFunc = () => referenceValue;
278+
var referenceValueExpression = referenceValueFunc.Body;
277279

278280
if (firstMemberAccessExpression == null)
279281
{
@@ -330,7 +332,7 @@ private static Expression<Func<T, bool>> BuildKeysetFilterPredicateExpression<T>
330332

331333
private static BinaryExpression MakeComparisonExpression<T>(
332334
KeysetPaginationItem<T> item,
333-
MemberExpression memberAccess, ConstantExpression referenceValue,
335+
MemberExpression memberAccess, Expression referenceValue,
334336
Func<Expression, Expression, BinaryExpression> compare)
335337
where T : class
336338
{
@@ -340,11 +342,14 @@ private static BinaryExpression MakeComparisonExpression<T>(
340342
// LessThan/GreaterThan operators are not valid for some types such as strings and guids.
341343
// We use the CompareTo method on these types instead.
342344

343-
// entity.Property.CompareTo(constant) >|< 0
345+
// entity.Property.CompareTo(referenceValue) >|< 0
344346
// -----------------------------------------
345347

346-
// entity.Property.CompareTo(constant)
347-
var methodCallExpression = Expression.Call(memberAccess, compareToMethod, referenceValue);
348+
// entity.Property.CompareTo(referenceValue)
349+
var methodCallExpression = Expression.Call(
350+
memberAccess,
351+
compareToMethod,
352+
EnsureMatchingType(memberAccess, referenceValue));
348353

349354
// >|< 0
350355
return compare(methodCallExpression, ConstantExpression0);
@@ -361,21 +366,18 @@ private static Expression EnsureMatchingType(
361366
MemberExpression memberExpression,
362367
Expression targetExpression)
363368
{
364-
// If the member is nullable we'll have to make sure the target type matches or else comparison/equal
365-
// expressions won't work because of unmatching types.
366-
if (IsNullableType(memberExpression.Type) && memberExpression.Type != targetExpression.Type)
369+
// If the target has a different type we should convert it.
370+
// Originally this happened with nullables only, but now that we use expressions
371+
// for the target access instead of constants we'll need this or else comparison won't work
372+
// between unmatching types (i.e int (member) compared to object (target)).
373+
if (memberExpression.Type != targetExpression.Type)
367374
{
368375
return Expression.Convert(targetExpression, memberExpression.Type);
369376
}
370377

371378
return targetExpression;
372379
}
373380

374-
private static bool IsNullableType(Type type)
375-
{
376-
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
377-
}
378-
379381
private static Func<Expression, Expression, BinaryExpression> GetComparisonExpressionToApply<T>(
380382
KeysetPaginationDirection direction, KeysetPaginationItem<T> item, bool orEqual)
381383
where T : class

0 commit comments

Comments
 (0)