对于我的通用网格,我目前这样做是为了激活排序:

Elements.OrderBy(column.SortExpression).AsQueryable();

其中 SortExpression 是 Func<T, object> 类型,column 是一个泛型类 Column<T>
我在这样的 Controller 中设置了 SortExpression:
new Column<OrderViewData>{Key = "ShippingDate", SortExpression = e => e.ShippingDate}

'OrderBy' 导致执行 sql 语句,这是我不想要的。

所以我试图用这个替换它:
Elements = from element in Elements
           orderby column.SortExpression
           select element;

这不会触发 sql 执行。

现在,当然 column.SortExpression 应该是另一种类型。只有我无法真正弄清楚它应该是什么类型以及如何在 Controller 中的泛型类上设置它。

我应该仍然能够以某种通用的强类型方式设置 SortExpression。

关于如何通过在应用程序中其他地方设置的表达式进行排序,而不在将订单应用于 IQueryable 时执行 sql 的任何建议?

@Earwicker:

这有效:
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();

并生成:
SELECT COUNT(*) AS [value]
FROM [dbo].[Employees] AS [t0]

当我替换 DateTime 时?在对象的第一行:
Expression<Func<Employee, object>> sortexpression = e => e.BirthDate;

我收到一个 InvalidOperationException:无法按类型“System.Object”订购

现在,您可能会说:“那么只使用 DateTime?”,但我希望在通用网格中构建列以尽可能减少代码量。我不希望人们必须输入整个 Expression<Func<Employee, some_type>> 。我希望人们能够像我第一次尝试 SortExpression = e => e.BirthDate 那样输入一些小的东西,在那里我利用通用 Column 类来定义“T”。

你认为有可能创建某种扩展,以某种方式获取 e.BirthDate 的类型,然后将 Func<T, object> 转换为 Expression<Func<T,some_type>> 吗?
然后我可以在内部代码中做一些事情,比如:
Elements.OrderBy(column.SortExpression.FixCast())

我现在不太关心我的内部代码是否丑陋或复杂。我需要正确执行 SQL 查询并注意使用网格的开发人员的可用性。

非常感谢你帮助我!

@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.


}

最佳答案

SortExpression 应该是 Expression<Func<T, object>> 类型。

通过将其设为 Func<T, object> ,您可以让编译器将其直接缩减为 IL,准备执行。 Linq to SQL(或实体,或 NHibernate,或其他)需要以表达式树的形式捕获的代码,以便它可以将其转换为 SQL 或其他一些查询语言,以便在其他地方执行。通过将您的 lambda 分配给 Expression<Func<...>>,您可以触发对表达式树的编译。

如果你放这个有用吗?

Elements = Elements.OrderBy(e => e.ShippingDate);

这个怎么样?
Expression<Func<OrderViewData, object>> sortExpression = e => e.ShippingDate;
Elements = Elements.OrderBy(sortExpression);

根据您更新的问题,听起来您需要使用静态类型的返回值而不是 object 来捕获表达式。

很难知道什么是您的理想安排,但在您的原始设置代码中,您有:
new Column<OrderViewData>{Key = "ShippingDate", SortExpression = e => e.ShippingDate}

假设 Column 有两个类型参数,TElem(存储在列中的值的类型)和 TSort(要排序的值的类型)。
new Column<Employee, DateTime?> { SortExpression = e => e.BirthDate }

这对我来说看起来不太笨拙,然后 SortExpression 将是:
Expression<Func<TElem, TSort>> SortExpression { get; set; }

关于c# - 订购 linq 查询,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/914681/

10-13 05:57