Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Linq处理OrderBy的变量数_C#_Linq_Linq To Entities - Fatal编程技术网

C# Linq处理OrderBy的变量数

C# Linq处理OrderBy的变量数,c#,linq,linq-to-entities,C#,Linq,Linq To Entities,我需要在Linq(to实体)语句中支持数量可变的Orderby术语。也就是说,我的函数将接受一个属性列表,其中的数据应按顺序排列。属性可以有升序或降序排序。处理构造Linq查询的最佳方法是什么 谢谢 要按任意属性排序,需要构建表达式树以传递给OrderBy 要按任意数量的属性排序,您需要在循环中调用然后再调用。您应该能够按照以下方式执行操作: public IEnumerable<MyType> DoSomething(params Expression<Func<MyT

我需要在Linq(to实体)语句中支持数量可变的Orderby术语。也就是说,我的函数将接受一个属性列表,其中的数据应按顺序排列。属性可以有升序或降序排序。处理构造Linq查询的最佳方法是什么


谢谢

要按任意属性排序,需要构建表达式树以传递给
OrderBy


要按任意数量的属性排序,您需要在循环中调用
然后再调用

您应该能够按照以下方式执行操作:

public IEnumerable<MyType> DoSomething(params Expression<Func<MyType,object>>[] properties)
 {
     var query = // create LINQ query that returns IQueryable<MyType>
     query = query.OrderBy(properties.First());

     foreach (var property in properties.Skip(1))
     {
         query = query.ThenBy(property);
     }
 }

 …

 var results = DoSomething(() => x.Age, () => x.Height, () => x.LastName);
public IEnumerable DoSomething(参数表达式[]属性)
{
var query=//创建返回IQueryable的LINQ查询
query=query.OrderBy(properties.First());
foreach(properties.Skip(1)中的var属性)
{
query=query.ThenBy(属性);
}
}
…
var结果=剂量测量(()=>x.年龄,()=>x.身高,()=>x.姓氏);
您需要处理指定的属性少于2个的情况。

从开始,这可以成为一个很好的扩展方法:

public static class EnumerableExtensions
{
    public static IEnumerable<T> OrderByMany<T>(this IEnumerable<T> enumerable, 
        params Expression<Func<T, object>>[] expressions)
    {
        if (expressions.Length == 1)
            return enumerable.OrderBy(expressions[0].Compile());

        var query = enumerable.OrderBy(expressions[0].Compile());
        for (int i = 1; i < expressions.Length;i++)
        {
            query = query.ThenBy(expressions[i].Compile());
        }
        return query;

    }
}
这是可能的:

var people = new Person[]
                    {
                        new Person() {Name = "John", Age = 40},
                        new Person() {Name = "John", Age = 20},
                        new Person() {Name = "Agnes", Age = 11}
                    };

foreach(var per in  people.OrderByMany(x => x.Name, x => x.Age))
{
    Console.WriteLine("{0} Age={1}",per.Name,per.Age);
}
输出:

Agnes Age=11
John Age=20
John Age=40
更新

您可以添加另一个重载的
OrderByMany
方法来支持SortOrder,尽管它很快就会变得笨重。就我个人而言,我只会选择语法

var query = from p 
            in people
            order by Name, Age descending;
然而,作为记录,至少在C#4中,我将使用枚举和元组来完成重载

public enum SortOrder
{
    Ascending, 
    Descending
}
还有额外的过载:

public static IEnumerable<T> OrderByMany<T>(this IEnumerable<T> enumerable,
    params Tuple<Expression<Func<T, object>>,SortOrder>[] expressions)
{

    var query = (expressions[0].Item2 == SortOrder.Ascending)
                    ? enumerable.OrderBy(expressions[0].Item1.Compile())
                    : enumerable.OrderByDescending(expressions[0].Item1.Compile());

    for (int i = 1; i < expressions.Length; i++)
    {
        query = expressions[i].Item2 == SortOrder.Ascending
                    ? query.ThenBy(expressions[i].Item1.Compile())
                    : query.ThenByDescending(expressions[i].Item1.Compile());
    }
    return query;

}
公共静态IEnumerable OrderByMany(此IEnumerable可枚举,
参数元组[]表达式)
{
变量查询=(表达式[0]。项2==排序器。升序)
?enumerable.OrderBy(表达式[0].Item1.Compile())
:enumerable.OrderByDescending(表达式[0].Item1.Compile());
for(int i=1;i
用法变得笨拙且难以阅读:

foreach (var per in people.OrderByMany(
                    new Tuple<Expression<Func<Person, object>>, SortOrder>(x => x.Age, SortOrder.Descending), 
                    new Tuple<Expression<Func<Person, object>>, SortOrder>(x => x.Name, SortOrder.Ascending)))
{
    Console.WriteLine("{0} Age={1}", per.Name, per.Age);
}
foreach(people.OrderByMany中的变量per)(
新元组(x=>x.Age,SortOrder.Descending),
新元组(x=>x.Name,SortOrder.升序)))
{
WriteLine(“{0}Age={1}”,per.Name,per.Age);
}

我喜欢Jamiec的想法,但我讨厌使用元组,因为语法很难看。因此,我构建了一个小型类来封装元组,并使用更好的变量名公开Item1和Item2属性的getter

还请注意,我使用了升序的默认排序顺序,因此如果要按降序排序,只需指定排序器

public class SortExpression<T>
{
    private Tuple<Expression<Func<T, object>>, SortOrder> tuple;        

    public SortExpression( Expression<Func<T, object>> expression, SortOrder order =SortOrder.Ascending )
    {
        tuple = new Tuple<Expression<Func<T,object>>, SortOrder>(expression, order);
    }

    public Expression<Func<T, object>> Expression {
        get { return tuple.Item1; }
    }

    public SortOrder Order {
        get { return tuple.Item2; }
    }
}
公共类SortExpression
{
私有元组;
公共排序表达式(表达式表达式,排序顺序=SortOrder.升序)
{
tuple=新的tuple(表达式、顺序);
}
公开表达{
获取{return tuple.Item1;}
}
公共分拣令{
获取{return tuple.Item2;}
}
}
在我的特定应用程序中,我有一个repository基类,它接受IQueryable并将其转换为ObservableCollection。在该方法中,我使用SortExpression类:

public ObservableCollection<T> GetCollection(params SortExpression<T>[] sortExpressions) {
    var list = new ObservableCollection<T>();
    var query = FindAll();

    if (!sortExpressions.Any()) {
        query.ToList().ForEach(list.Add);
        return list;
    }

    var ordered = (sortExpressions[0].Order == SortOrder.Ascending)
        ? query.OrderBy(sortExpressions[0].Expression.Compile())
        : query.OrderByDescending(sortExpressions[0].Expression.Compile());

    for (var i = 1; i < sortExpressions.Length; i++) {
        ordered = sortExpressions[i].Order == SortOrder.Ascending
            ? ordered.ThenBy(sortExpressions[i].Expression.Compile())
            : ordered.ThenByDescending(sortExpressions[i].Expression.Compile());
    }

    ordered.ToList().ForEach(list.Add);
    return list;
}        
public-observeCollection-GetCollection(参数SortExpression[]sortExpressions){
var list=新的ObservableCollection();
var query=FindAll();
如果(!sortExpressions.Any()){
query.ToList().ForEach(list.Add);
退货清单;
}
var ordered=(sortExpressions[0]。Order==SortOrder.升序)
?query.OrderBy(sortExpressions[0].Expression.Compile())
:query.OrderByDescending(sortExpressions[0].Expression.Compile());
对于(变量i=1;i
以下是正在使用的方法:

var repository = new ContactRepository(UnitOfWork);
return repository.GetCollection(
                    new SortExpression<Contact>(x => x.FirstName),
                    new SortExpression<Contact>(x => x.LastName));       
var repository=新联系人存储库(UnitOfWork);
return repository.GetCollection(
新的SortExpression(x=>x.FirstName),
新的SortExpression(x=>x.LastName));

谢谢!OrderBYMany是否可以修改为支持传递IComparer?忽略上面的内容。我添加了IComparer很好。如何修改它以通过升序和降序排序。一个很好的答案!您还可以编写一个GetTuple扩展。请看一个例子。这样一来,阅读起来就容易多了!:)@JerryKur你能告诉我你是如何添加IComparer的吗?在添加
IComparer comparer
作为参数后,myy Visual Studio在OrderBy方法调用时抱怨说,
无法从用法推断方法“Enumerable.OrderBy(IEnumerable,Func,IComparer)”的类型参数。尝试显式指定类型参数。
var repository = new ContactRepository(UnitOfWork);
return repository.GetCollection(
                    new SortExpression<Contact>(x => x.FirstName),
                    new SortExpression<Contact>(x => x.LastName));