I create an IOrderedQueryable
and want to use the query on different lists later in the process. But all I get are empty results.
My code for creating the query:
IOrderedQueryable<SomeElement> sortingQuery;
if (userInputA)
{
sortingQuery = new List<SomeElement>().AsQueryable()
.OrderBy(clt => clt.PropertyA);
}
else
{
sortingQuery = new List<SomeElement>().AsQueryable()
.OrderBy(clt => cltPropertyB);
}
sortingQuery = userInputB
? sortingQuery.ThenBy(clt => clt.PropertyC ?? int.MaxValue)
: sortingQuery.ThenByDescending(clt => clt.PropertyD ?? int.MaxValue);
sortingQuery = sortingQuery.ThenBy(clt => clt.PropertyZ);
Later I want to execute the query on n lists:
while(process)
{
List<SomeElement> data = await GetNewData();
var orderedData = data.AsQueryable()
.Provider
.CreateQuery<SomeElement>(sortingQuery.Expression)
.ToList();
//...
}
Unfortunately, the orderedData
list is always empty, regardless of the data.Count()
.
What am I doing wrong?
I create an IOrderedQueryable
and want to use the query on different lists later in the process. But all I get are empty results.
My code for creating the query:
IOrderedQueryable<SomeElement> sortingQuery;
if (userInputA)
{
sortingQuery = new List<SomeElement>().AsQueryable()
.OrderBy(clt => clt.PropertyA);
}
else
{
sortingQuery = new List<SomeElement>().AsQueryable()
.OrderBy(clt => cltPropertyB);
}
sortingQuery = userInputB
? sortingQuery.ThenBy(clt => clt.PropertyC ?? int.MaxValue)
: sortingQuery.ThenByDescending(clt => clt.PropertyD ?? int.MaxValue);
sortingQuery = sortingQuery.ThenBy(clt => clt.PropertyZ);
Later I want to execute the query on n lists:
while(process)
{
List<SomeElement> data = await GetNewData();
var orderedData = data.AsQueryable()
.Provider
.CreateQuery<SomeElement>(sortingQuery.Expression)
.ToList();
//...
}
Unfortunately, the orderedData
list is always empty, regardless of the data.Count()
.
What am I doing wrong?
Share Improve this question edited Jan 29 at 17:46 marc_s 757k184 gold badges1.4k silver badges1.5k bronze badges asked Jan 29 at 14:23 HWS-SLSHWS-SLS 1668 bronze badges2 Answers
Reset to default 2You don't need to use an empty list to create a queryable. You can just apply the queryable expression using a function. Also lists aren't really IQueryable
, you may as well return IEnumerable
IOrderedEnumerable<SomeElement> GetSortedQuery(IEnumerable<SomeElement> list, bool userInputA, bool userInputB)
{
var sortingQuery = userInputA
? list.OrderBy(clt => clt.PropertyA)
: list.OrderBy(clt => cltPropertyB);
sortingQuery = userInputB
? sortingQuery.ThenBy(clt => clt.PropertyC ?? int.MaxValue)
: sortingQuery.ThenByDescending(clt => clt.PropertyD ?? int.MaxValue);
sortingQuery = sortingQuery.ThenBy(clt => clt.PropertyZ);
return sortingQuery;
}
Then just do
while (process)
{
List<SomeElement> data = await GetNewData();
var orderedData = GetSortedQuery(data, userInputA, userInputB);
//...
}
I would encapsulate everything into helper classes to simplify usage. However, I do not recommend using EnumerableQuery
if performance is a concern.
Updated Code Using New Extension Methods:
var sortingQuery = Enumerable.Empty<SomeElement>().CreateTemplateQuery();
if (userInputA)
sortingQuery = sortingQuery.OrderBy(clt => clt.PropertyA);
else
sortingQuery = sortingQuery.OrderBy(clt => clt.PropertyB);
sortingQuery = userInputB
? sortingQuery.ThenBy(clt => clt.PropertyC ?? int.MaxValue)
: sortingQuery.ThenByDescending(clt => clt.PropertyD ?? int.MaxValue);
sortingQuery = sortingQuery.ThenBy(clt => clt.PropertyZ);
Reusing the Sorting Logic Later:
while (process)
{
List<SomeElement> data = await GetNewData();
var orderedData = data.ApplyOrderTemplate(sortingQuery)
.ToList();
// Further processing...
}
Implementation of Helper Classes:
public static class OrderingHelper
{
static readonly IQueryProvider EnumerableProvider = Array.Empty<int>().AsQueryable().Provider;
static class OrderHelperImpl<T>
{
// A placeholder that can be easily replaced
public static ParameterExpression Anchor = Expression.Parameter(typeof(IQueryable<T>), "anchor");
public static IOrderedQueryable<T> CreateTemplateQuery()
{
return (IOrderedQueryable<T>)EnumerableProvider.CreateQuery<T>(Anchor);
}
}
public static IOrderedQueryable<T> CreateTemplateQuery<T>(this IEnumerable<T> enumerable)
{
return OrderHelperImpl<T>.CreateTemplateQuery();
}
public static IOrderedQueryable<T> ApplyOrderTemplate<T>(this IEnumerable<T> source, IQueryable<T> template)
{
var visitor = new ReplacingVisitor(OrderHelperImpl<T>.Anchor, source.AsQueryable().Expression);
var newExpression = visitor.Visit(template.Expression);
return (IOrderedQueryable<T>)EnumerableProvider.CreateQuery<T>(newExpression);
}
class ReplacingVisitor : ExpressionVisitor
{
private readonly Expression _original;
private readonly Expression _replacement;
public ReplacingVisitor(Expression original, Expression replacement)
{
_original = original;
_replacement = replacement;
}
[return: NotNullIfNotNull(nameof(node))]
public override Expression? Visit(Expression? node)
{
return node == _original ? _replacement : base.Visit(node);
}
}
}
Why This Approach Is Inefficient:
This method is not ideal for performance because EnumerableProvider
dynamically generates a compiled delegate for each enumeration, leading to unnecessary overhead.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745292201a4620928.html
评论列表(0条)