简体   繁体   中英

Dynamic Linq Build Where Clause many Parameters

I will explain my Problem

so Firstly, I use Predicates Linq for Build Where clause dynamically. I have to build dynamically because I don't know how many parameters will come. Let me give an example. For the A column can be one parameters however, for the B column can be 2 parameters like either value 'Gas' or 'Oil' which select but that's big problem I can not combine for these 2 column correctly. So as a result, this code work but It return 0 Items. But there are I know.

public List<CarEntity> GetSearchByKCriteria(int cityId, List<string> fuelType, List<string> gearType, List<string> budget,
        List<string> caroser, List<string> enginePower)
    {
        Expression<Func<Car, bool>> query = null;
        Expression<Func<Car, bool>> combine = null;

        foreach (var bud in budget)
        {
            if (budget.Count >= 1)
            {
                if (bud == "1")
                {
                    if (budget.Count > 1)
                    {
                        query = car => car.Budget >= 20000 && car.Budget <= 34999;
                    }
                    else
                    {
                        query = car => car.Budget >= 20000 && car.Budget <= 34999;
                    }

                }
                else if (bud == "2")
                {

                    if (query != null)
                    {
                        combine = car => (car.Budget >= 35000 && car.Budget <= 49999);
                        query = query.Or(combine);

                    }
                    else
                    {
                        query = car => car.Budget >= 35000 && car.Budget <= 49999;

                    }
                }
            }
        }
        foreach (var caros in caroser)
        {
            if (caros != "-1" && !string.IsNullOrEmpty(caros))
            {
                if (query != null)
                {
                    if (query.Expand().ToString().ToLower().Contains("karoser"))
                    {
                        combine = car => (car.Karoser == caros);
                        query = query.And(combine);

                    }
                    else
                    {
                        combine = car => car.Karoser == caros;
                        query = query.And(combine);

                    }

                }
                else
                {
                    query = car => car.Karoser == caros;
                }
            }
        }
        foreach (var fuel in fuelType)
        {
            if (fuel != "-1" && !string.IsNullOrEmpty(fuel))
            {
                if (query != null)
                {
                    if (query.Expand().ToString().ToLower().Contains("yakituru"))
                    {
                        combine = car => (car.YakitTuru==fuel);
                        query = query.Or(combine);

                    }
                    else
                    {
                        combine = car => car.YakitTuru == fuel;
                        query = query.And(combine);

                    }

                }
                else
                {
                    query = car => car.YakitTuru == fuel;
                }
            }
        }
        foreach (var gear in gearType)
        {
            if (gear!="-1"&& !string.IsNullOrEmpty(gear))
            {
                if (query != null)
                {
                    if (query.Expand().ToString().ToLower().Contains("sanzimantipi"))
                    {
                        combine = car => (car.SanzimanTipi == gear);
                        query = query.Or(combine);

                    }
                    else
                    {
                        combine = car => car.SanzimanTipi == gear;
                        query = query.And(combine);

                    }

                }
                else
                {
                    query = car => car.SanzimanTipi == gear;
                } 
            }
        }
        foreach (var engine in enginePower)
        {
            if (enginePower.Count >= 1)
            {
                if (engine == "1")
                {
                    if (query != null)
                    {
                        if (query.Expand().ToString().ToLower().Contains("silindirhacmi"))
                        {
                            combine = car => (car.SilindirHacmi >= 0 && car.SilindirHacmi <= 1600);
                            query = query.Or(combine);

                        }
                        else
                        {
                            combine = car => (car.SilindirHacmi >= 0 && car.SilindirHacmi <= 1600);
                            query = query.And(combine);

                        }

                    }
                    else
                    {
                        query = car => car.SilindirHacmi >= 0 && car.SilindirHacmi <= 1600;
                    }
                }

                if (engine == "3")
                {
                    if (query != null)
                    {
                        if (query.Expand().ToString().ToLower().Contains("silindirhacmi"))
                        {
                            combine = car => (car.SilindirHacmi >= 1601 && car.SilindirHacmi <= 1800);
                            query = query.Or(combine);

                        }
                        else
                        {
                            combine = car => (car.SilindirHacmi >= 1601 && car.SilindirHacmi <= 1800);
                            query = query.And(combine);

                        }

                    }
                    else
                    {
                        query = car => car.SilindirHacmi >= 1601 && car.SilindirHacmi <= 1800;
                    }
                }

        }

        using (var context = DataContextFactory.CreateContext())
        {

            var result = (from fkCar in context.Car.Where(query)
                          join pkCarBrand in context.CarBrand on fkCar.Marka equals pkCarBrand.ID
                          where fkCar.IsActive == true

                          select new
                          {
                              entity = fkCar,
                              joinEntity = pkCarBrand
                          });
            List<CarEntity> theCarList = new List<CarEntity>();
            foreach (var item in result)
            {
                CarEntity theEntity = Mapper.Map(item.entity);
                theEntity.CarBrand = Mapper.Map(item.joinEntity);
                theCarList.Add(theEntity);

            }
            return theCarList;
        }
    }

So thanks for reply,

I faced a similar challenge a while back, where I wanted to have a list of allowed values for an attribute where, if matched, the associated instance would pass the filter. I came up with the following extension method:

static public Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
{
    if (null == valueSelector)
    {
        throw new ArgumentNullException("valueSelector");
    }
    if (null == values) { throw new ArgumentNullException("values"); }

    ParameterExpression p = valueSelector.Parameters.Single();
    if (!values.Any())
    {
        return e => false;
    }

    var equals = values.Select(value => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));
    var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));
    return Expression.Lambda<Func<TElement, bool>>(body, p);
}

This is based on the discussion and code posted at http://www.velocityreviews.com/forums/t645784-linq-where-clause.html

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