简体   繁体   中英

How can I simplify this Entity Framework code?

I have a complex search function that allows the user to select from a list of fields, then choose a search value and also a modifier. For example if this was a shopping cart, the user is searching products and can search products matching:

Name contains "ball" Price less than "5.00" Shipping out of "United States"

etc..

My problem is, I have 25 different fields to search on, some are complex relating to child and grandchild objects. So for each field I have an if structure like:

if (mod == "!=")
{
    allInvestigators = allInvestigators.Where(i => !i.Indicators.Any(j => j.Title.ToLower().Contains(txtVal)));
}
else if (mod == "==")
{
    allInvestigators = allInvestigators.Where(i => i.Indicators.Any(j => j.Title.ToLower() == txtVal));
}
else
{
    allInvestigators = allInvestigators.Where(i => i.Indicators.Any(j => j.Title.ToLower().Contains(txtVal)));
}

So to make it clear, the user can pick a field, a search modifier (==, <, >, !=) and can use several of these filters in one search! Does anyone have any ideas on how to shrink this code?

UPDATE THis is where I am now..

allInvestigators = allInvestigators.Where(i => 
                                (i.Address.State.ToLower().Contains(txtVal) && mod == "=") ||
                                (i.Address.State.ToLower() == txtVal && mod == "==") ||
                                (i.Address.State.ToLower() != txtVal && mod == "!=")
                            );

You could try putting the field queries into list of variables and ten being able to cycle through them and applying them properly. Not full code, just for inspiration:

Expression<Func<Item, Boolean>> expr = j => j.Title.ToLower().Contains(txtVal);
allInvestigators = allInvestigators.Where(i => !i.Indicators.AsQueryable().Any(expr));

Take a look at PredicateBuilder that is described in "C# 4.0/5.0 in a Nutshell"

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;

public static class PredicateBuilder
{
  public static Expression<Func<T, bool>> True<T> ()  { return f => true;  }
  public static Expression<Func<T, bool>> False<T> () { return f => false; }

  public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
                                                      Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
  }

  public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
                                                       Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
  }
}

It can be used to build Expression/ Specification first.

You can find examples of AndSpecification , OrSpecification , NotSpecification in the blog post Specifications Pattern with LINQ that are similar to PredicateBuilder idea.

You can use String.Equals

allInvestigators = allInvestigators.Where(i => 
                            (i.Address.State.ToLower().Contains(txtVal) && mod == "=") ||
                            (i.Address.State.Equals(txtVal, StringComparison.CurrentCultureIgnoreCase) && mod == "==") ||
                            (!i.Address.State.Equals(txtVal, StringComparison.CurrentCultureIgnoreCase) && mod == "!=")
                        );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM