Reputation: 3538
I have following function that prepare data for jquery datatable grid. Now I am facing following error for Datatype other than string
Unable to cast the type 'System.DateTime' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types.
Code:
public GeneralResponse<IEnumerable<Holiday>> GetHolidays(string filter,
int initialPage,
int pageSize,
out int totalRecords,
out int recordFilterd,
int sortColumn,
string sortDirection)
{
var response = new GeneralResponse<IEnumerable<Holiday>>();
totalRecords = 0;
recordFilterd = 0;
filter = filter.Trim().ToLower();
try
{
Expression<Func<Holiday, dynamic>> expr;
switch (sortColumn)
{
case 0:
expr = p => p.HolidayDate;
break;
case 1:
expr = p => p.Name;
break;
case 2:
expr = p => p.ExchangeMarket.Name;
break;
default:
expr = p => p.CreatedOn;
break;
}
var data = holidayRepository.Query(true);
//var data = holidayRepository.GetAll(true).AsQueryable(); previous working one
totalRecords = data.Count();
//filter
if (!string.IsNullOrWhiteSpace(filter))
{
data = data.Where(x => x.Name.ToLower().Contains(filter));
//todo : Add date search as well
}
recordFilterd = data.Count();
//sort
data = sortDirection == "asc" ? data.OrderBy(expr) : data.OrderByDescending(expr);
data = data
.Skip(initialPage * pageSize)
.Take(pageSize);
var result = data.ToList();
response.Data = result;
}
catch (Exception e)
{
response.Error = true;
response.Exception = e;
}
return response;
}
// This method is under generic repository
public IQueryable<T> Query()
{
return Query(false);
}
earlier I was using IEnumerable which was first loading all data in list & then performing filter which was working fine (but not correct or best practice)
Now I am stuck with the filter part. How can I fix this error to have order by all type of property column?
I did lots of research but could not found the any solution.
Upvotes: 3
Views: 844
Reputation: 205749
dynamic
or object
cannot be used as TKey
generic argument of EF Queryable.OrderBy
(actually in any Queryable
method expression) - it has to be the actual type of the key. Which in turn means you cannot use a common Expression<Func<...>>
variable to hold the keySelector
expression.
The solution is to use conditional .OrderBy[Descending]
inside your switch
/ case
block.
To make handling the ascending/descending option easier (and avoid expression duplication), start by creating a simple custom extension method like this:
namespace System.Linq
{
public static class QueryableExtensions
{
public static IOrderedQueryable<TSource> OrderBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, bool ascending)
{
return ascending ? source.OrderBy(keySelector) : source.OrderByDescending(keySelector);
}
}
}
Then move the switch
/ case
block after the
recordFilterd = data.Count();
line and use the above helper method inside:
bool ascending = sortDirection == "asc";
switch (sortColumn)
{
case 0:
data = data.OrderBy(p => p.HolidayDate, ascending);
break;
case 1:
data = data.OrderBy(p => p.Name, ascending);
break;
case 2:
data = data.OrderBy(p => p.ExchangeMarket.Name, ascending);
break;
default:
data = data.OrderBy(p => p.CreatedOn, ascending);
break;
}
Upvotes: 7