我在VS2008的示例中找到了一个关于动态LINQ的例子,允许你使用类似SQL语句的字符串(例如OrderBy("Name, Age DESC"))
进行排序。不幸的是,该方法只适用于IQueryable<T>
。是否有办法在IEnumerable<T>
上实现这个功能呢?
我在VS2008的示例中找到了一个关于动态LINQ的例子,允许你使用类似SQL语句的字符串(例如OrderBy("Name, Age DESC"))
进行排序。不幸的是,该方法只适用于IQueryable<T>
。是否有办法在IEnumerable<T>
上实现这个功能呢?
public static IEnumerable<T> OrderBy( this IEnumerable<T> input, string queryString) {
//parse the string into property names
//Use reflection to get and sort by properties
//something like
foreach( string propname in queryString.Split(','))
input.OrderBy( x => GetPropertyValue( x, propname ) );
// I used Kjetil Watnedal's reflection example
}
< p > GetPropertyValue
函数来自 Kjetil Watnedal 的回答
问题是为什么?任何这样的排序都会在运行时抛出异常,而不是编译时(比如 D2VIANT 的答案)。
如果你正在处理 Linq to Sql 并且 orderby 是表达式树,它将被转换为 SQL 以进行执行。
public List<Book> Books(string orderField, bool desc, int skip, int take)
{
var propertyInfo = typeof(Book).GetProperty(orderField);
return _context.Books
.Where(...)
.OrderBy(p => !desc ? propertyInfo.GetValue(p, null) : 0)
.ThenByDescending(p => desc ? propertyInfo.GetValue(p, null) : 0)
.Skip(skip)
.Take(take)
.ToList();
}
我找到了一些有趣的东西。 如果您的数据源是DataTable,您可以使用动态排序而不必使用动态Linq。
DataTable orders = dataSet.Tables["SalesOrderHeader"];
EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
orderby order.Field<DateTime>("OrderDate")
select order;
DataView view = query.AsDataView();
bindingSource1.DataSource = view;
参考:http://msdn.microsoft.com/en-us/library/bb669083.aspx(使用 DataSetExtensions)
这里还有一种方法,通过将其转换为 DataView 来实现:
DataTable contacts = dataSet.Tables["Contact"];
DataView view = contacts.AsDataView();
view.Sort = "LastName desc, FirstName asc";
bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();
您可以将IEnumerable转换为IQueryable。
items = items.AsQueryable().OrderBy("Name ASC");
public IEnumerable<Order> GetOrders()
{
// i use Dapper to return IEnumerable<T> using Query<T>
//.. do stuff
return orders // IEnumerable<Order>
}
IQueryable版本
public IQueryable<Order> GetOrdersAsQuerable()
{
IEnumerable<Order> qry= GetOrders();
// use the built-in extension method AsQueryable in System.Linq namespace
return qry.AsQueryable();
}
现在,您可以使用IQueryable版本来绑定例如Asp.net中的GridView,并受益于排序(您无法使用IEnumerable版本进行排序)。
我使用Dapper作为ORM,构建了IQueryable版本,并在Asp.net中的GridView中利用排序非常容易。
Dictionary<string, Func<Item, object>> SortParameters = new Dictionary<string, Func<Item, object>>()
{
{"Rank", x => x.Rank}
};
并且像这样使用:
yourList.OrderBy(SortParameters["Rank"]);
另一种解决方案使用以下类/接口。它不是真正的动态,但它可以工作。
public interface IID
{
int ID
{
get; set;
}
}
public static class Utils
{
public static int GetID<T>(ObjectQuery<T> items) where T:EntityObject, IID
{
if (items.Count() == 0) return 1;
return items.OrderByDescending(u => u.ID).FirstOrDefault().ID + 1;
}
}
多亏了Maarten (在LINQ中使用PropertyInfo对象查询集合),我得到了这个解决方案:
myList.OrderByDescending(x => myPropertyInfo.GetValue(x, null)).ToList();
foreach (PropertyInfo column in (new Process()).GetType().GetProperties())
{
if (column.Name == dgvProcessList.Columns[e.ColumnIndex].Name)
{}
}
或者
PropertyInfo column = (new Process()).GetType().GetProperties().Where(x => x.Name == dgvProcessList.Columns[e.ColumnIndex].Name).First();
请确保您的列名与对象属性匹配
干杯
IOrderedEnumerable<JToken> sort;
if (query.OrderBys[0].IsDESC)
{
sort = jarry.OrderByDescending(r => (string)r[query.OrderBys[0].Key]);
}
else
{
sort = jarry.OrderBy(r =>
(string) r[query.OrderBys[0].Key]);
}
foreach (var item in query.OrderBys.Skip(1))
{
if (item.IsDESC)
{
sort = sort.ThenByDescending(r => (string)r[item.Key]);
}
else
{
sort = sort.ThenBy(r => (string)r[item.Key]);
}
}
将List转换为IEnumerable或Iquerable,添加using System.LINQ.Dynamic命名空间,然后您可以在逗号分隔的字符串中提及属性名称以OrderBy方法,默认来自System.LINQ.Dynamic。
OrderBy
不会保持之前的顺序!! - Amir Ismail