0

I am trying to find the best way to implement a service method that can get the data and also the consumer must have option to specify the coumnname in which the result has to be sorted.

[OperationContract]
void GetAllMoviesSorted();

public List<MovieData> GetAllMoviesSorted()
{
    return db.GetAllData(); 
}

The option I thought was to pass a column name enum as a parameter to the function and build a dynamic query. Is this the best way to implement this?

Regards, Jebli.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Rad
  • 391
  • 4
  • 14
  • Why not sort, on the client after you fetch the data? – Pantelis Jun 15 '14 at 13:22
  • The requirement is to do it on the service side.I am sure that there should be some better option. The simplest think that i can do is to write LINQ query for sorting based on the column name. – Rad Jun 15 '14 at 13:55

3 Answers3

0

If the columns to sort by are MovieData Class Properties:

public List<MovieData> getAllMoviesSorted(string column)
{
    List<MovieData> movieData = db.GetAllData();
    switch(column.ToUpper())
    {
        case "ORDERDATE":
            movieData = movieData.OrderBy(o=>o.OrderDate).ToList(); 
            break;
        // add more cases
        default:
            throw new Exception("Column " + column + " cannot be found.");       
    }
    return movieData;
}
Lucas
  • 86
  • 1
0

Thought I'd do a generic reflective version of @Lucas 's answer.

public List<MovieData> getAllMoviesSorted(string column)
{
    List<MovieData> movieData = db.GetAllData();
    var parameter = Expression.Parameter(typeof(MovieData));
    var lambda = Expression.Lambda(
                    Expression.PropertyOrField(parameter, column),
                    parameter);
    return movieData
            .AsQueryable()
            .OrderBy(lambda)
            .ToList();
}
Aron
  • 15,464
  • 3
  • 31
  • 64
0

I have found a much simpler way without using expression trees

 PropertyInfo pi = typeof(MovieData).GetProperty(orderbycolumn);
 values.OrderBy(x => pi.GetValue(x, null));

Please find the below sample code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace sfPerformance
{
    class MoviesDynamicOrderBy
    {
        static void Main(string[] args)
        {
            IQueryable<MovieData> MovieNameList = new List<MovieData>() { 
            new MovieData {Name = "Star Wars" , Rating = 7, Language = "Hollywood"},
            new MovieData {Name = "The Godfather" , Rating = 7, Language = "Hollywood"},
            new MovieData {Name = "The Lord Of The Rings" , Rating = 8, Language = "Hollywood"},
            new MovieData {Name = "Titanic" , Rating = 10, Language = "Hollywood"},
            new MovieData {Name = "Gone With The Wind" , Rating = 9, Language = "Hollywood"}            
            }.AsQueryable();

            //Ascending default
            MoviesDynamicOrderBy obj = new MoviesDynamicOrderBy();
            var result = obj.StudentOrderByColumn<MovieData>("Name", MovieNameList);

            foreach (var item in result)
            {
                Console.WriteLine(item.Name);
            }

            Console.WriteLine(Environment.NewLine);

            //Descending  
            var descendingResult = obj.StudentOrderByColumn<MovieData>("Name", MovieNameList, true);

            foreach (var item in descendingResult)
            {
                Console.WriteLine(item.Name);
            } 

            if (System.Diagnostics.Debugger.IsAttached)
                Console.Read(); 
        }

        public IOrderedQueryable<MovieData> StudentOrderByColumn<T>(string orderbycolumn, IQueryable<MovieData> values, bool isDescending = false) 
        { 
            PropertyInfo pi = typeof(MovieData).GetProperty(orderbycolumn);
            IOrderedQueryable<MovieData> sortedMovies;
            if(isDescending)
             sortedMovies = values.OrderByDescending(x => pi.GetValue(x, null)); 
            else 
             sortedMovies = values.OrderBy(x => pi.GetValue(x, null));

            return sortedMovies;
        }
    }

    public class MovieData
    {
        public string Name { get; set; }
        public int Rating { get; set; }
        public string Language { get; set; }
    }
}
Rad
  • 391
  • 4
  • 14