Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ public static dynamic FirstOrDefault([NotNull] this IQueryable source, [NotNull]
/// </example>
[PublicAPI]
public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, [NotNull] string resultSelector, object[] args)
{
{
return InternalGroupBy(source, config, keySelector, resultSelector, null, args);
}

Expand All @@ -695,7 +695,7 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] Par
return InternalGroupBy(source, config, keySelector, resultSelector, equalityComparer, args);
}

internal static IQueryable InternalGroupBy([NotNull] IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, [NotNull] string resultSelector, IEqualityComparer equalityComparer, object[] args)
internal static IQueryable InternalGroupBy([NotNull] IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, [NotNull] string resultSelector, IEqualityComparer equalityComparer, object[] args)
{
Check.NotNull(source, nameof(source));
Check.NotNull(config, nameof(config));
Expand All @@ -705,7 +705,7 @@ internal static IQueryable InternalGroupBy([NotNull] IQueryable source, [NotNul
bool createParameterCtor = config?.EvaluateGroupByAtDatabase ?? SupportsLinqToObjects(config, source);
LambdaExpression keyLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, keySelector, args);
LambdaExpression elementLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, resultSelector, args);

Expression optimized = null;
if (equalityComparer == null)
{
Expand All @@ -720,9 +720,9 @@ internal static IQueryable InternalGroupBy([NotNull] IQueryable source, [NotNul
optimized = OptimizeExpression(Expression.Call(
typeof(Queryable), nameof(Queryable.GroupBy),
new[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },
source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda),
source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda),
Expression.Constant(equalityComparer, equalityComparerGenericType)));
}
}

return source.Provider.CreateQuery(optimized);
}
Expand Down Expand Up @@ -804,7 +804,7 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] str
/// </example>
[PublicAPI]
public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, [CanBeNull] params object[] args)
{
{
return InternalGroupBy(source, config, keySelector, null, args);
}

Expand Down Expand Up @@ -1598,19 +1598,19 @@ internal static IOrderedQueryable InternalOrderBy([NotNull] IQueryable source, [
foreach (DynamicOrdering dynamicOrdering in dynamicOrderings)
{
if (comparer == null)
{
{
queryExpr = Expression.Call(
typeof(Queryable), dynamicOrdering.MethodName,
new[] { source.ElementType, dynamicOrdering.Selector.Type },
queryExpr, Expression.Quote(Expression.Lambda(dynamicOrdering.Selector, parameters)));
}
else
{
var comparerGenericType = typeof(IComparer<>).MakeGenericType(dynamicOrdering.Selector.Type);
var comparerGenericType = typeof(IComparer<>).MakeGenericType(dynamicOrdering.Selector.Type);
queryExpr = Expression.Call(
typeof(Queryable), dynamicOrdering.MethodName,
new[] { source.ElementType, dynamicOrdering.Selector.Type },
queryExpr, Expression.Quote(Expression.Lambda(dynamicOrdering.Selector, parameters)),
queryExpr, Expression.Quote(Expression.Lambda(dynamicOrdering.Selector, parameters)),
Expression.Constant(comparer, comparerGenericType));
}
}
Expand Down Expand Up @@ -2504,7 +2504,7 @@ public static IOrderedQueryable<TSource> ThenBy<TSource>([NotNull] this IOrdered
{
return (IOrderedQueryable<TSource>)InternalThenBy((IOrderedQueryable)source, config, ordering, comparer, args);
}

/// <summary>
/// Performs a subsequent ordering of the elements in a sequence in ascending order according to a key.
/// </summary>
Expand Down Expand Up @@ -2569,7 +2569,7 @@ internal static IOrderedQueryable InternalThenBy([NotNull] IOrderedQueryable sou
foreach (DynamicOrdering dynamicOrdering in dynamicOrderings)
{
if (comparer == null)
{
{
queryExpr = Expression.Call(
typeof(Queryable), dynamicOrdering.MethodName,
new[] { source.ElementType, dynamicOrdering.Selector.Type },
Expand Down Expand Up @@ -2684,6 +2684,12 @@ public static IQueryable Where([NotNull] this IQueryable source, [NotNull] Lambd
var optimized = OptimizeExpression(Expression.Call(typeof(Queryable), nameof(Queryable.Where), new[] { source.ElementType }, source.Expression, Expression.Quote(lambda)));
return source.Provider.CreateQuery(optimized);
}

/// <inheritdoc cref="DynamicQueryableExtensions.Where(IQueryable, LambdaExpression)"/>
public static IQueryable<TSource> Where<TSource>([NotNull] this IQueryable<TSource> source, [NotNull] LambdaExpression lambda)
{
return (IQueryable<TSource>)Where((IQueryable)source, lambda);
}
#endregion

#region Private Helpers
Expand Down
36 changes: 35 additions & 1 deletion test/System.Linq.Dynamic.Core.Tests/QueryableTests.Where.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.Linq.Dynamic.Core.Tests.Helpers;
using System.Linq.Dynamic.Core.Tests.Helpers.Entities;
using System.Linq.Dynamic.Core.Tests.Helpers.Models;
using System.Linq.Expressions;
using FluentAssertions;
using Xunit;

namespace System.Linq.Dynamic.Core.Tests
Expand Down Expand Up @@ -103,6 +105,38 @@ public void Where_Dynamic_DateTime_Equals_Null()
Assert.Equal(expected, result2);
}

[Fact]
public void Where_Dynamic_IQueryable_LambdaExpression()
{
// Arrange
var queryable = (IQueryable)new[] { new User { Income = 5 } }.AsQueryable();

Expression<Func<User, bool>> userExpression = u => u.Income > 1;
LambdaExpression lambdaExpression = userExpression;

// Act
var result = queryable.Where(lambdaExpression);

// Assert
result.Should().HaveCount(1);
}

[Fact]
public void Where_Dynamic_IQueryableT_LambdaExpression()
{
// Arrange
var queryable = new[] { new User { Income = 5 } }.AsQueryable();

Expression<Func<User, bool>> userExpression = u => u.Income > 1;
LambdaExpression lambdaExpression = userExpression;

// Act
var result = queryable.Where(lambdaExpression);

// Assert
result.Should().HaveCount(1);
}

[Fact]
public void Where_Dynamic_Exceptions()
{
Expand All @@ -116,7 +150,7 @@ public void Where_Dynamic_Exceptions()
Assert.Throws<ParseException>(() => qry.Where("Id=123"));

Assert.Throws<ArgumentNullException>(() => DynamicQueryableExtensions.Where(null, "Id=1"));
Assert.Throws<ArgumentNullException>(() => qry.Where(null));
Assert.Throws<ArgumentNullException>(() => qry.Where((string)null));
Assert.Throws<ArgumentException>(() => qry.Where(""));
Assert.Throws<ArgumentException>(() => qry.Where(" "));
}
Expand Down