Hello Stackers.
For my generic grid I currently do this to activate the sorting:
Elements.OrderBy(column.SortExpression).AsQueryable();
In which SortExpression is of type Func<T, object>
and column is a generic class Column<T>
I set SortExpression in a controller like this:
new Column<OrderViewData>{Key = "ShippingDate", SortExpression = e => e.ShippingDate}
The 'OrderBy' causes an execution of the sql statement, which I don't want.
So I'm trying to replace it with this:
Elements = from element in Elements
orderby column.SortExpression
select element;
Which doesn't trigger the sql execution.
Now, ofcourse column.SortExpression should be of another type. Only I can't really figure out what type it should be and how to set it on the generic class in the controller.
I should still be able to set SortExpression in a generic strongtyped way of some sort.
Any suggestions on how I can order by an expression set somewhere else in the application, without executing the sql when applying the order to the IQueryable?
@ Earwicker:
This works:
Expression<Func<Employee, DateTime?>> sortexpression = e => e.BirthDate;
var db = new NorthwindDataContext();
var query = from e in db.Employees
select e;
query = query.OrderBy(sortexpression);
int count = query.Count();
and generates:
SELECT COUNT(*) AS [value]
FROM [dbo].[Employees] AS [t0]
When I replace DateTime? in the first line with object:
Expression<Func<Employee, object>> sortexpression = e => e.BirthDate;
I get an InvalidOperationException: Cannot order by type 'System.Object'
Now, you might say: "then just use DateTime?", but I'd like building the columns in my generic grid to require the least amount of code possible. I don't want people to have to type the whole Expression<Func<Employee, some_type>>
. I want people to be able to just type something small like my first attempt SortExpression = e => e.BirthDate
, where I take advantage of the generic Column class to define 'T'.
Do you think it would be possible to create some kind of extension that somehow gets the type of e.BirthDate
and then casts the Func<T, object>
to Expression<Func<T,some_type>>
?
Then I could do something in the internal code like:
Elements.OrderBy(column.SortExpression.FixCast())
I don't care much that my internal code is ugly or complex at this moment. I need to get the SQL queries right & take care of usability for developers using the grid.
Thanks a lot for helping me out!
@ earwicker 2:
var gridBuilder = new RainbowGridBuilder<Employee>("Examples_Employees")
{
Elements = GetEmployees(), //The elements (records) we will show in our grid.
//Define the columns for our grid.
Columns = new List<Column<Employee>>{
new Column<Employee> {
Key = "EmployeeId", //Key is used for sorting, selecting columns, ...
Header = "Employee Id", //The header of the column. Also used as caption in the column selection checkboxlist.
ValueExpression = e => e.EmployeeID.ToString(), //The Linq expression which will be executed on each element to fill the cell
SortExpression = e => e.EmployeeID, //The Linq expression by which to sort the elements in the grid.
Display = false}, //Is this column visible by default?
new Column<Employee> {Key = "Name", ValueExpression = e => e.FirstName + " " + e.LastName, SortExpression = e => e.LastName},
},
// Some other properties here that are irrelevant.
}