订购linq查询

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

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

其中SortExpression的类型为Func和column是generics类Column

我在这样的控制器中设置了SortExpression:

 new Column{Key = "ShippingDate", SortExpression = e => e.ShippingDate} 

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

所以我试图用这个替换它:

 Elements = from element in Elements orderby column.SortExpression select element; 

哪个不会触发sql执行。

现在,当然column.SortExpression应该是另一种类型。 只有我无法确定它应该是什么类型以及如何在控制器中的generics类上设置它。

我仍然可以使用某种通用的强类型方式设置SortExpression。

有关如何通过表达式在应用程序中的其他位置进行排序的任何建议,而不是在将顺序应用于IQueryable时执行sql?

@Ewwicker:

这有效:

 Expression<Func> 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> sortexpression = e => e.BirthDate; 

我得到一个InvalidOperationException:无法按类型’System.Object’排序

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

你认为有可能创建某种扩展,以某种方式得到e.BirthDate的类型,然后将FuncExpression<Func> ? 然后我可以在内部代码中执行一些操作,如:Elements.OrderBy(column.SortExpression.FixCast())

我不太关心我的内部代码目前是丑陋还是复杂。 我需要正确地获取SQL查询,并为使用网格的开发人员提供可用性。

非常感谢帮助我!

@ earwicker 2:

 var gridBuilder = new RainbowGridBuilder("Examples_Employees") { Elements = GetEmployees(), //The elements (records) we will show in our grid. //Define the columns for our grid. Columns = new List<Column>{ new Column { 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 {Key = "Name", ValueExpression = e => e.FirstName + " " + e.LastName, SortExpression = e => e.LastName}, }, // Some other properties here that are irrelevant. } 

SortExpression应为Expression>

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

你把这个放了吗?

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

那怎么样?

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

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

很难知道什么是理想的安排,但在您的原始设置代码中,您有:

 new Column{Key = "ShippingDate", SortExpression = e => e.ShippingDate} 

假设Column采用了两个类型参数: TElem (存储在列中的值的种类)和TSort (要排序的值的类型)。

 new Column { SortExpression = e => e.BirthDate } 

这对我来说看起来并不太笨重,而SortExpression则只是:

 Expression> SortExpression { get; set; } 

我想出了一个解决方案,实现了我的目标。

用法:在列上设置强类型排序表达式:

 Columns = new List>{ new Column { Key = "EmployeeId", SortExpression = new SortExpression(e => e.EmployeeID) // ... other irrelevant column properties ... }, new Column { Key = "EmployeeBirthDate", SortExpression = new SortExpression(e => e.BirthDate) } }; 

基础代码

RainbowGridBuilder类中“buildGrid()”方法中的这几行应用排序:

 if (columnToSort != null) //sort the elements according to the set column key and the sortexpression { var column = Columns.Where(c => c.Key == columnToSort).SingleOrDefault(); if (column != null) { Elements = column.SortExpression.ApplySortExpression(Elements, descending); } } 

这个怎么运作:

通过在我创建的SortExpression类中使用重载的构造函数,我可以设置一个私有的Expression>

在SortExpression类中是一个方法ApplySortExpression,它搜索非null私有成员并相应地进行排序:

 public class SortExpression { private Expression> DateTimeExpression { get; set; } private Expression> intExpression { get; set; } private Expression> stringExpression { get; set; } public SortExpression(Expression> expression) { DateTimeExpression = expression; } public SortExpression(Expression> expression) { intExpression = expression; } public SortExpression(Expression> expression) { stringExpression = expression; } public IQueryable ApplySortExpression(IQueryable elements, bool? descending) { if (DateTimeExpression != null) { if (descending.HasValue && descending.Value) return elements.OrderByDescending(DateTimeExpression); else return elements.OrderBy(DateTimeExpression); } else if (intExpression != null) { if (descending.HasValue && descending.Value) return elements.OrderByDescending(intExpression); else return elements.OrderBy(intExpression); } else if (stringExpression != null) { if (descending.HasValue && descending.Value) return elements.OrderByDescending(stringExpression); else return elements.OrderBy(stringExpression); } else throw new Exception("Unsuported sortkey type"); } } 

这个解决方案在引擎盖下可能不是很干净,但这是我追求的可用性。 消费代码的唯一变化是添加“ new SortExpression ”。

我认为问题的根源是由于您转换为Queryable 之前执行了OrderBy。 如果您在IEnumerable 上订购,那么您需要先订购。 与IQueryable 不同,IEnumerable 不构建表达式树…它围绕另一个包装一个可枚举。 要获得延迟执行的好处,您需要确保从一开始就使用IQueryable。 在执行所有过滤,排序等后转换为一个将不会提供任何好处。

这是我对这个orderby问题的简单解决方案:

  var SampleData = new SampleDataContext(); var text = from i in SampleData.Events select i; var text2 = text.OrderByDescending(i => i.id); return View(text2);