diff --git a/src/MR.EntityFrameworkCore.KeysetPagination/KeysetPaginationExtensions.cs b/src/MR.EntityFrameworkCore.KeysetPagination/KeysetPaginationExtensions.cs index efe1fa2..3eedece 100644 --- a/src/MR.EntityFrameworkCore.KeysetPagination/KeysetPaginationExtensions.cs +++ b/src/MR.EntityFrameworkCore.KeysetPagination/KeysetPaginationExtensions.cs @@ -254,7 +254,7 @@ private static Expression> BuildKeysetFilterPredicateExpression var referenceValues = GetValues(items, reference); var firstMemberAccessExpression = default(MemberExpression); - var firstReferenceValueExpression = default(ConstantExpression); + var firstReferenceValueExpression = default(Expression); // entity => var param = Expression.Parameter(typeof(T), "entity"); @@ -273,7 +273,9 @@ private static Expression> BuildKeysetFilterPredicateExpression var isInnerLastOperation = j + 1 == innerLimit; var item = items[j]; var memberAccess = Expression.MakeMemberAccess(param, item.Property); - var referenceValueExpression = Expression.Constant(referenceValues[j]); + var referenceValue = referenceValues[j]; + Expression> referenceValueFunc = () => referenceValue; + var referenceValueExpression = referenceValueFunc.Body; if (firstMemberAccessExpression == null) { @@ -330,7 +332,7 @@ private static Expression> BuildKeysetFilterPredicateExpression private static BinaryExpression MakeComparisonExpression( KeysetPaginationItem item, - MemberExpression memberAccess, ConstantExpression referenceValue, + MemberExpression memberAccess, Expression referenceValue, Func compare) where T : class { @@ -340,11 +342,14 @@ private static BinaryExpression MakeComparisonExpression( // LessThan/GreaterThan operators are not valid for some types such as strings and guids. // We use the CompareTo method on these types instead. - // entity.Property.CompareTo(constant) >|< 0 + // entity.Property.CompareTo(referenceValue) >|< 0 // ----------------------------------------- - // entity.Property.CompareTo(constant) - var methodCallExpression = Expression.Call(memberAccess, compareToMethod, referenceValue); + // entity.Property.CompareTo(referenceValue) + var methodCallExpression = Expression.Call( + memberAccess, + compareToMethod, + EnsureMatchingType(memberAccess, referenceValue)); // >|< 0 return compare(methodCallExpression, ConstantExpression0); @@ -361,9 +366,11 @@ private static Expression EnsureMatchingType( MemberExpression memberExpression, Expression targetExpression) { - // If the member is nullable we'll have to make sure the target type matches or else comparison/equal - // expressions won't work because of unmatching types. - if (IsNullableType(memberExpression.Type) && memberExpression.Type != targetExpression.Type) + // If the target has a different type we should convert it. + // Originally this happened with nullables only, but now that we use expressions + // for the target access instead of constants we'll need this or else comparison won't work + // between unmatching types (i.e int (member) compared to object (target)). + if (memberExpression.Type != targetExpression.Type) { return Expression.Convert(targetExpression, memberExpression.Type); } @@ -371,11 +378,6 @@ private static Expression EnsureMatchingType( return targetExpression; } - private static bool IsNullableType(Type type) - { - return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); - } - private static Func GetComparisonExpressionToApply( KeysetPaginationDirection direction, KeysetPaginationItem item, bool orEqual) where T : class