过滤实体,然后按动态字段排序

发布于 2024-11-02 06:26:27 字数 1193 浏览 1 评论 0原文

我试图首先过滤一组产品,然后

  (repository.GetAllProducts()
     .Where(x=>x.Naam.Contains("filter")) as ObjectQuery<Product>)
     .FunkyOrder<Product>(sortfield,sortdirection)

使用扩展方法订购它们:(

 public  static IEnumerable<T> FunkyOrder<T>(this ObjectQuery<T> input, string fieldname = "Id", string sortdirection = "asc")
        {            
            switch (sortdirection)
            {
                case "dsc":
                case "desc":
                    return input.OrderBy("it." + fieldname + " DESC");
                default:
                    return input.OrderBy("it." + fieldname);

            }
        }

我的存储库的 GetAllProducts() 返回一个 IEnumerable

这个 FunkyOrder 方法应该可以工作,但是 - 作为 ObjectQuery - 强制转换返回 NULL

我只能使用FunkyOrder 与 ObjectQuery 因为这似乎是唯一支持那些“it.FieldName”查询的东西,

如果我将 - as - 表示法更改为常规转换,我会得到:

 Unable to cast object of type 'WhereEnumerableIterator`1[MySecretNameSpace.Product]' to type 'System.Data.Objects.ObjectQuery`1[MySecretNameSpace.Product]'.

有什么方法可以使这项工作正常进行吗?要么在过滤之前进行排序,要么用 lambda 表达式编写一个巨大的 switch 来进行排序?

I'm trying to FIRST filter a set of products, then order them

  (repository.GetAllProducts()
     .Where(x=>x.Naam.Contains("filter")) as ObjectQuery<Product>)
     .FunkyOrder<Product>(sortfield,sortdirection)

Using the Extension method:

 public  static IEnumerable<T> FunkyOrder<T>(this ObjectQuery<T> input, string fieldname = "Id", string sortdirection = "asc")
        {            
            switch (sortdirection)
            {
                case "dsc":
                case "desc":
                    return input.OrderBy("it." + fieldname + " DESC");
                default:
                    return input.OrderBy("it." + fieldname);

            }
        }

(the GetAllProducts() of my Repository returns an IEnumerable

This FunkyOrder method should be working but that - as ObjectQuery - cast returns NULL

I can only use the FunkyOrder with ObjectQuery because that seems to be the only thing that supports those "it.FieldName" queries.

If I change the - as - notation to A regular cast I get:

 Unable to cast object of type 'WhereEnumerableIterator`1[MySecretNameSpace.Product]' to type 'System.Data.Objects.ObjectQuery`1[MySecretNameSpace.Product]'.

Is there any way to make this work or will I be forced to either live with sorting before filtering, or write a giant switch with lambda expressions for my sorting?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浅听莫相离 2024-11-09 06:26:27

这实际上是一个令人头疼的问题。但最终,事实证明,通过一点黑客行为和反思,它实际上很容易完成:

public class Program
{
    public class SomeClass
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    static void Main(string[] args)
    {
        List<SomeClass> sample = new List<SomeClass>
        {
            new SomeClass { Id = 4, Name = "ABC" },
            new SomeClass { Id = 1, Name = "XYZ" },
            new SomeClass { Id = 2, Name = "JKL" }
        };

        var result = sample.OrderByDynamic("Name", OrderDirection.Ascending).ToList();

        result.ForEach(x => Console.WriteLine("Id: " + x.Id + " | Name: " + x.Name));

        Console.ReadKey();
    }
}

public enum OrderDirection
{
    Ascending,
    Descending
}

public static class LinqExtensions
{
    public static IEnumerable<T> OrderByDynamic<T>(this IEnumerable<T> source, string propertyName, OrderDirection direction = OrderDirection.Ascending)
    {
        if(direction == OrderDirection.Ascending)
            return source.OrderBy(x => x.GetType().GetProperty(propertyName).GetValue(x, null));
        else
            return source.OrderByDescending(x => x.GetType().GetProperty(propertyName).GetValue(x, null));
    }
}

这个例子在测试情况下对我有用;我可以提供属性名称,并指定排序方向,效果很好。只需像这样调用:

yourEnumerable.OrderByDynamic("YourPropertyName");
yourEnumerable.OrderByDynamic("YourPropertyName", OrderDirection.Descending);

享受!

This actually turned out to be a GIANT headache to try to solve; but in the end, it actually turned out being very easy to accomplish with a bit of hackishness and reflection:

public class Program
{
    public class SomeClass
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    static void Main(string[] args)
    {
        List<SomeClass> sample = new List<SomeClass>
        {
            new SomeClass { Id = 4, Name = "ABC" },
            new SomeClass { Id = 1, Name = "XYZ" },
            new SomeClass { Id = 2, Name = "JKL" }
        };

        var result = sample.OrderByDynamic("Name", OrderDirection.Ascending).ToList();

        result.ForEach(x => Console.WriteLine("Id: " + x.Id + " | Name: " + x.Name));

        Console.ReadKey();
    }
}

public enum OrderDirection
{
    Ascending,
    Descending
}

public static class LinqExtensions
{
    public static IEnumerable<T> OrderByDynamic<T>(this IEnumerable<T> source, string propertyName, OrderDirection direction = OrderDirection.Ascending)
    {
        if(direction == OrderDirection.Ascending)
            return source.OrderBy(x => x.GetType().GetProperty(propertyName).GetValue(x, null));
        else
            return source.OrderByDescending(x => x.GetType().GetProperty(propertyName).GetValue(x, null));
    }
}

This example worked for me in test situations; I could supply the property name, and specify a sort direction, and it worked great. Simply call like so:

yourEnumerable.OrderByDynamic("YourPropertyName");
yourEnumerable.OrderByDynamic("YourPropertyName", OrderDirection.Descending);

Enjoy!

清醇 2024-11-09 06:26:27

我会将您的 FunkyOrder 方法更改为 IEnumerable 并通过动态创建表达式来实现动态排序,这样

public static IEnumerable<T> FunkyOrder<T, TResult>(this IEnumerable<T> input, string fieldname = "Id", string sortdirection = "asc")
{
 ParameterExpresssion parameter = Expression.Parameter(typeof(T), "p");
 Expression property = Expression.PropertyOrField(parameter, fieldname);

 var lambda = Expression.Lambda<Func<T, TResult>>(property, parameter)

 if(sortdirection == "asc")
 {
  return input.OrderBy(lambda.Compile());
 }
 else
 {
  return input.OrderByDescending(lambda.Complile());
 }
}

您将不再需要转换为 ObjectQuery

I would change your FunkyOrder method to IEnumerable and implement your dynamic sorting by creating an Expression dynamically like so

public static IEnumerable<T> FunkyOrder<T, TResult>(this IEnumerable<T> input, string fieldname = "Id", string sortdirection = "asc")
{
 ParameterExpresssion parameter = Expression.Parameter(typeof(T), "p");
 Expression property = Expression.PropertyOrField(parameter, fieldname);

 var lambda = Expression.Lambda<Func<T, TResult>>(property, parameter)

 if(sortdirection == "asc")
 {
  return input.OrderBy(lambda.Compile());
 }
 else
 {
  return input.OrderByDescending(lambda.Complile());
 }
}

You will no longer need to cast to ObjectQuery

快乐很简单 2024-11-09 06:26:27

您可以使用 Dynamic Linq 用于动态过滤和排序。这个小库(只有一个源文件)包含 IQueryable 的扩展方法,例如:

public static IQueryable<T> Where<T>(this IQueryable<T> source,
    string predicate, params object[] values)

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source,
    string ordering, params object[] values)

//...and more like GroupBy, Select

您对 IEnumerable 的查询可以写为:

repository.GetAllProducts().AsQueryable()
    .Where(x => x.Naam.Contains("filter"))
    .OrderBy("FieldName desc")

该库实现了执行这些动态查询所需的所有反射代码。

You can use Dynamic Linq for dynamic filtering and sorting. This small library (only one single source file) contains extension methods of IQueryable<T> like:

public static IQueryable<T> Where<T>(this IQueryable<T> source,
    string predicate, params object[] values)

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source,
    string ordering, params object[] values)

//...and more like GroupBy, Select

Your query on IEnumerable could then be written as:

repository.GetAllProducts().AsQueryable()
    .Where(x => x.Naam.Contains("filter"))
    .OrderBy("FieldName desc")

The library implements all the necessary reflection code to perform those dynamic queries.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文