0

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,

YigitV
  • 13
  • 2
  • You'll have a hard time getting a good answer if you can't narrow down your problem a little. Nobody wants to read 150+ lines of your code for free, especially when it looks like half of them are identical. – StriplingWarrior Apr 17 '14 at 22:33

1 Answers1

1

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

Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • It's worth noting that LINQ to Entities now supports `.Contains()` in query expressions. – StriplingWarrior Apr 17 '14 at 22:22
  • @StriplingWarrior: Good to know. As of when? – Eric J. Apr 17 '14 at 22:22
  • Hmmm... I think it was .NET 4.0. It makes a tidy little `WHERE IN` clause. I used to have a method just like this one, but now there's not much call for it anymore. – StriplingWarrior Apr 17 '14 at 22:29
  • @EricJ. thanks for reply but to be honestly i did not implement to my project exactly. if you have leissure time can you tell me on the samples or my code thanks. – YigitV Apr 17 '14 at 22:36
  • @YigitV: You might want to consider submitting your code to codereview.stackexchange.com first, to get it simplified to the point where people can understand what it does. – StriplingWarrior Apr 17 '14 at 22:49
  • @StriplingWarrior: EF releases are independent of .NET releases. You can use .Contains() if you first call .AsEnumerable(), but that Contains() will run in the .NET layer rather than on the DB, potentially causing many extra records to be retrieved from the DB just to be tossed in the application. – Eric J. Apr 17 '14 at 23:20
  • @EricJ. I think that this problem about the query not the about either contains or '==' because when I was changed query like 'and' or 'or' it still build wrong where clause – YigitV Apr 18 '14 at 07:24
  • @EricJ.: "Entity Framework 4" then? I don't remember which version it started in, but I guarantee that if you say "ctx.MyThings.Where(t => thingIds.Contains(t.ThingId))" you'll get a nice little WHERE IN statement if `thingIds` is an in-memory list. – StriplingWarrior Apr 18 '14 at 23:06