I have a func as part of specification class which sorts the given iqueryable
Func<IQueryable<T>, IOrderedQueryable<T>>? Sort { get; set; }
When i add more than one condition to the func like below , it results in stack overflow exception.
spec.OrderBy(sc => sc.Case.EndTime).OrderBy(sc => sc.Case.StartTime);
The OrderBy method is implemented like this
public ISpecification<T> OrderBy<TProperty>(Expression<Func<T, TProperty>> property)
{
_ = Sort == null ? Sort = items => items.OrderBy(property) : Sort = items => Sort(items).ThenBy(property);
return this;
}
Chaining or using separate lines doesn't make a difference.
This problem gets resolved if I assign a new instance of the specification and set it's func, but i don't want to be assigning to a new instance everytime. Please suggest what am i missing here and how to reuse the same instance (if possible).
CodePudding user response:
This is the problematic part:
Sort = items => Sort(items)
That's like writing a method that calls itself.
What you want is to evaluate the existing Sort
function, not "the result of the Sort
property at the time of evaluation".
I would rewrite the method like this:
public ISpecification<T> OrderBy<TProperty>(Expression<Func<T, TProperty>> property)
{
var existingSort = Sort;
Sort = existingSort is null
? items => items.OrderBy(property)
: items => existingSort(items).ThenBy(property);
return this;
}
(I would also echo D-Shih's comment - this is a somewhat counter-intuitive approach, and counter to normal LINQ. Maybe you have some particular reason to go against LINQ's expectations of immutability and chaining, but it's definitely unusual.)