First of all, let me apologize in case the title doesn't make sense. I'm having a hard time understanding what I'm doing, let alone being able to use the right words for describing what I'm doing.
I'm building a generic grid class in which I define the columns by a header / linq expression combination:
public class Column<T>
{
public string Header { get; set; }
public Func<T, string> ValueExpression { get; set; }
}
Usage:
Columns = new List<Column<Employee>>
{
new Column<Employee> {Header = "Employee Id", ValueExpression = e => e.EmployeeID.ToString()},
new Column<Employee> {Header = "Name", ValueExpression = e => e.FirstName + " " + e.LastName},
new Column<Employee> {Header = "Employee Birthday Year", ValueExpression = e => e.BirthDate.HasValue ? e.BirthDate.Value.Year.ToString() : ""}
},
I want to project the ValueExpression's (Func<T, string>
) on an IQueryable 'employees':
var db = new NorthwindDataContext();
var employees = db.Employees.Select(e => e);
I can get that to work while extracting a IEnumerable<IEnumerable<string>>
from employees (a list of lists of strings used in my views) like this:
var elementsList = employees.ToPagedList(PageIndex, PageSize);
var elementStringList = elementsList.ToStringList(Columns.Select(c => c.ValueExpression).ToArray());
Don't mind the PagedList stuff, it's irrelevant and kinda the same as ToList();
Here's the ToStringList() Extension method:
public static IEnumerable<IEnumerable<string>> ToStringList<T>(this IPagedList<T> enumerable, params Func<T, string>[] fields)
{
foreach (var element in enumerable)
yield return element.ToStringList(fields);
}
private static IEnumerable<string> ToStringList<T>(this T element, params Func<T, string>[] fields)
{
foreach (var field in fields)
yield return field(element);
}
The problem is that this approach involves executing the IQueryable before specifying the fields that have to be returned.
As a result, the following query gets executed somewhere along the way:
SELECT [t0].[EmployeeID], [t0].[LastName], [t0].[FirstName], [t0].[Title], [t0].[TitleOfCourtesy], [t0].[BirthDate], [t0].[HireDate], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[HomePhone], [t0].[Extension], [t0].[Photo], [t0].[Notes], [t0].[ReportsTo], [t0].[PhotoPath]
FROM [dbo].[Employees] AS [t0]
As you might figure, it is undesired to retrieve ALL fields from the table Employees.
I'm looking for a way to somehow build an extension method on the IQueryable employees in which I can pass a List of Func's (the "ValueExpression" members of Column) and "build" a new IQuerable that way, that will execute SQL that just retrieves the needed fields from the database.
So I'm looking for something like this:
IQueryable employees = employees.SelectByExpressions(Columns.Select(c => c.ValueExpression).ToArray());
Thanks in advance.