Reputation: 18363
I'm trying to make a repository class that has a method to order the results based upon a "sort" parameter. I need to pass it as a parameter since I'm trying to be very strict that my repository doesn't return IQueryable and only returns List. The problem is that I have no idea how to make it so that it meets the following requirements:
Is this even possible or is it useless that a Repository allows returning with ordering? Should the repository be just able to perform CRUD operations? Maybe returning IQueryable would be the best option?
Upvotes: 2
Views: 5173
Reputation: 1504062
Perhaps you need something like this:
public class Ordering<T>
{
private readonly Func<IQueryable<T>, IOrderedQueryable<T>> transform;
private Ordering(Func<IQueryable<T>, IOrderedQueryable<T>> transform)
{
this.transform = transform;
}
public static Ordering<T> Create<TKey>
(Expression<Func<T, TKey>> primary)
{
return new Ordering<T>(query => query.OrderBy(primary));
}
public Ordering<T> ThenBy<TKey>(Expression<Func<T, TKey>> secondary)
{
return new Ordering<T>(query => transform(query).ThenBy(secondary));
}
// And more for the descending methods...
internal IOrderedQueryable<T> Apply(IQueryable<T> query)
{
return transform(query);
}
}
Then a client can create an Ordering<T>
to be passed into the repository, and the repositry can call Apply
with the IQueryable<T>
. Does that make sense?
Sample (slightly silly) use:
var ordering = Ordering<FileInfo>.Create(fi => fi.Length)
.ThenBy(fi => fi.Name);
Upvotes: 8
Reputation: 564931
I would argue that returning the IQueryable<T>
directly is typically the best option.
For example, say you have a method that queries your DB to return a specific table or view. If the client of your repository only needs the first 10 records, with custom criteria and a sort you weren't expecting, you can allow this by returning IQueryable<T>
. The client just needs to add the .Where(...).OrderBy(...).Take(10);
With IQueryable<T>
, the call across the data layer will automatically adapt, and only pull the 10 records across. If you return a List instead, your DB query will pull every record, and then the filtering will need to happen in your application.
This adds a huge processing/network/etc overhead, with no real reason.
Upvotes: 2
Reputation: 27581
This is arguable, but I think your repository should just return the data. Let your consuming classes worry about the ordering of the set.
The thought process behind this is pretty simple, the consuming classes decide the order anyway. So they can pass that to hand crafted orderby generator in your repository and let it do the work, or they can just use linq and order the set they get back from the repository. I think the latter option is easier to implement, less prone to bugs, and will make more sense when reading the code, but once again, I think my point is arguable.
Upvotes: 4