重构 OrderBy 表达式

发布于 2024-07-11 05:56:31 字数 1595 浏览 5 评论 0原文

我希望能够重构 linq 表达式中的 OrderBy 子句。

以下是重构 where 子句

before:

results = ctx.ActiveUsers
    .Where(u => u.CompanyID != 1 &&
           (u.LastName.ToLower().Contains(searchString)
           || u.Email.ToLower().Contains(searchString)
           || u.Company.Name.ToLower().Contains(searchString)))
    .OrderBy(u =>  u.LastName ).ThenBy(u => u.FirstName)
    .Select(u => new Employee {
      ID = u.ID
      , FirstName = u.FirstName
      , LastName = u.LastName
      , Email = u.Email
      , CompanyName = u.Company.Name
      , CompanyID = u.CompanyID.ToString() });

after:

results = ctx.ActiveUsers
    .Where(Employee.GetExpression(searchString))
    .OrderBy(u =>  u.LastName ).ThenBy(u => u.FirstName)
    .Select(u => new Employee {
      ID = u.ID
      , FirstName = u.FirstName
      , LastName = u.LastName
      , Email = u.Email
      , CompanyName = u.Company.Name
      , CompanyID = u.CompanyID.ToString() });

private static Expression<Func<User, bool>> GetExpression(string searchString)
{ 
    Expression<Func<User, bool>> p = (u => u.CompanyID != 1 &&
                       (u.LastName.ToLower().Contains(searchString)
                       || u.Email.ToLower().Contains(searchString)
                       || u.Company.Name.ToLower().Contains(searchString)));
    return p;
}

我想知道是否可以实现相同类型的事情,除非我想重构 Orderby 表达式。

先感谢您

I would like to be able to refactor out the OrderBy clause in a linq expression.

Here is an example of a refactor of the where clause

before:

results = ctx.ActiveUsers
    .Where(u => u.CompanyID != 1 &&
           (u.LastName.ToLower().Contains(searchString)
           || u.Email.ToLower().Contains(searchString)
           || u.Company.Name.ToLower().Contains(searchString)))
    .OrderBy(u =>  u.LastName ).ThenBy(u => u.FirstName)
    .Select(u => new Employee {
      ID = u.ID
      , FirstName = u.FirstName
      , LastName = u.LastName
      , Email = u.Email
      , CompanyName = u.Company.Name
      , CompanyID = u.CompanyID.ToString() });

after:

results = ctx.ActiveUsers
    .Where(Employee.GetExpression(searchString))
    .OrderBy(u =>  u.LastName ).ThenBy(u => u.FirstName)
    .Select(u => new Employee {
      ID = u.ID
      , FirstName = u.FirstName
      , LastName = u.LastName
      , Email = u.Email
      , CompanyName = u.Company.Name
      , CompanyID = u.CompanyID.ToString() });

private static Expression<Func<User, bool>> GetExpression(string searchString)
{ 
    Expression<Func<User, bool>> p = (u => u.CompanyID != 1 &&
                       (u.LastName.ToLower().Contains(searchString)
                       || u.Email.ToLower().Contains(searchString)
                       || u.Company.Name.ToLower().Contains(searchString)));
    return p;
}

I was wondering if the same type of thing would be possible except I would like to refactor the Orderby expression.

Thank you in advance

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

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

发布评论

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

评论(3

空心↖ 2024-07-18 05:56:31

假设您实际上想要获取“LastName”、“FirstName”等字符串,我会执行以下操作:

var unordered = ctx.ActiveUsers
                   .Where(Employee.GetExpression(searchString))
                   .OrderBy(ordering)
                   .Select(u => new Employee {
                       ID = u.ID,
                       FirstName = u.FirstName,
                       LastName = u.LastName,
                       Email = u.Email,
                       CompanyName = u.Company.Name,
                       CompanyID = u.CompanyID.ToString() });

并添加一个新的 OrderBy 扩展方法:

public static class UserQueryableExtensions
{
    public static IOrderedQueryable<User> OrderBy(this IQueryable<User> source,
                                                  string ordering)
    {
        switch (ordering)
        {
            case "LastName":
                return source.OrderBy(x => x.LastName);
            case "FirstName":
                return source.OrderBy(x => x.FirstName);
            case "Email":
                return source.OrderBy(x => x.Email);
            case "Company":
                return source.OrderBy(x => x.Company);
            default:
                throw new ArgumentException("Unknown ordering");
        }
    }
}

您当然可以使用反射来执行此操作,但是除非您有一组重要的属性(或者您想对不同的实体类型使用相同的例程),否则 switch 语句会更容易。

Assuming you want to actually take a string such as "LastName", "FirstName" etc, I'd do something like:

var unordered = ctx.ActiveUsers
                   .Where(Employee.GetExpression(searchString))
                   .OrderBy(ordering)
                   .Select(u => new Employee {
                       ID = u.ID,
                       FirstName = u.FirstName,
                       LastName = u.LastName,
                       Email = u.Email,
                       CompanyName = u.Company.Name,
                       CompanyID = u.CompanyID.ToString() });

and add a new OrderBy extension method:

public static class UserQueryableExtensions
{
    public static IOrderedQueryable<User> OrderBy(this IQueryable<User> source,
                                                  string ordering)
    {
        switch (ordering)
        {
            case "LastName":
                return source.OrderBy(x => x.LastName);
            case "FirstName":
                return source.OrderBy(x => x.FirstName);
            case "Email":
                return source.OrderBy(x => x.Email);
            case "Company":
                return source.OrderBy(x => x.Company);
            default:
                throw new ArgumentException("Unknown ordering");
        }
    }
}

You certainly could do this using reflection, but unless you have a significant set of properties (or you want to use the same routine for different entity types) a switch statement is easier.

本宫微胖 2024-07-18 05:56:31

谢谢乔恩,

这个答案让我现在走上了正确的道路......但是,
我需要在订单中保留 ThenBy 子句。 因此,虽然下面的解决方案不是动态的,但它仍然保留 ThenBy

var unordered = ctx.ActiveUsers
                   .Where(Employee.GetExpression(searchString))
                   .MyOrder()
                   .Select(u => new Employee {
                       ID = u.ID,
                       FirstName = u.FirstName,
                       LastName = u.LastName,
                       Email = u.Email,
                       CompanyName = u.Company.Name,
                       CompanyID = u.CompanyID.ToString() });

public static class UserQueryableExtensions
{
    public static IOrderedQueryable<User> MyOrder(this IQueryable<User> source )
    { 
        return source.OrderBy(x => x.LastName).ThenBy(x => x.FirstName).ThenBy(x => x.Email);
    }
}

thanks jon,

that answer put me on the right path for now... However,
I need to preserve the ThenBy clause in my order. so while the solution below is not dynamic it still preserves the ThenBy

var unordered = ctx.ActiveUsers
                   .Where(Employee.GetExpression(searchString))
                   .MyOrder()
                   .Select(u => new Employee {
                       ID = u.ID,
                       FirstName = u.FirstName,
                       LastName = u.LastName,
                       Email = u.Email,
                       CompanyName = u.Company.Name,
                       CompanyID = u.CompanyID.ToString() });

public static class UserQueryableExtensions
{
    public static IOrderedQueryable<User> MyOrder(this IQueryable<User> source )
    { 
        return source.OrderBy(x => x.LastName).ThenBy(x => x.FirstName).ThenBy(x => x.Email);
    }
}
伴我老 2024-07-18 05:56:31

我同意 Jon 的观点,即尽可能使用 lambda 以避免拼写错误等。但是,如果您确实无法做到这一点(无论出于何种原因),我已经在过去的。 请参阅此处在 LINQ-to-SQL 上测试的示例(但理论上使用 EF 应该没问题)。

I'd agree with Jon on using lambdas where possible to avoid typos etc. However, if you genuinely can't do this (for whatever reason), I've looked at fully-dynamic OrderBy in the past. See here for an example tested on LINQ-to-SQL (but it should be OK with EF in theory).

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