Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# generic orderby

In my base-repository class

i wrote this function to make possible to retrive a sorted data collection from the DB. T is a generic defined at Class level

public abstract class RepositoryBase<T> 
        where T : class

The code is this:

public IList<T> GetAll<TKey>(Expression<Func<T, bool>> whereCondition, Expression<Func<T, TKey>> sortCondition, bool sortDesc = false)
        {
            if (sortDesc)
                return this.ObjectSet.Where(whereCondition).OrderByDescending(sortCondition).ToList<T>();

            return this.ObjectSet.Where(whereCondition).OrderBy(sortCondition).ToList<T>() ;
        }

My goal was to introduce a generic sort parameter so that i could call the function in this way:

repo.GetAll (model=>model.field>0, model=>model.sortableField, true)

i mean that i could specify the sorting field directly via anonymous function and so using Intellisense...

Unfortunately this function doesn't work as the last code line generate errors at compile time.

I tried also to call:

repo.GetAll<Model> (model=>model.field>0, model=>model.sortableField, true)

but this don't work.

How should i write the function to meet my goal?

i'm working with EF 5, c#, .NET 4.5

like image 453
Alex Avatar asked Oct 21 '22 16:10

Alex


1 Answers

You're using ObjectSet which implements IQueryable<T>. That is extended by methods on System.Linq.Queryable, which accept Expression<Func< parameters. It is correct to use those Expression parameters, as you intend for execution to occur in the database, not locally.

  • A Func is an anonymous delegate, a .net method.
  • An Expression is a tree, which may be compiled into a Func, or may be translated into Sql or something else.

You showed us a really abstract use of the method, but not an actual use of the method, or the compiler error. I suspect the error you may be making is confusing the two type parameters.

You said:

repo.GetAll<Model> (model=>model.field>0, model=>model.sortableField, true)

But this generic parameter for this method represents the type of sortableField. If sortableField isn't a Model - this is wrong.

Instead, you should be doing something like this:

Repository<Person> myRepo = new Repository<Person>();
myRepo.GetAll<DateTime>(p => p.Friends.Count() > 3, p => p.DateOfBirth, true);

If specifying the sort type breaks your intended pattern of usage, consider hiding that key by using an IOrderer: Store multi-type OrderBy expression as a property

like image 117
Amy B Avatar answered Oct 24 '22 10:10

Amy B