简体   繁体   中英

LINQ Conditional Where Clauses not working

Using: MVC 5, C#, VS 2013, EF6 with CodeFirst, SQL Server 2012

I have tried the four different ways to get the data without any issues.

IQueryable<vw_Results> qryResults = _db.vw_Results;

The problem I am encountering is that I have 13 filter options and the code for all 13 follow the same logic:

string fmVal = string.Empty;
if (!string.IsNullOrEmpty(form["Locations"]))
{
    fmVal = form["Locations"].ToString();
    qryResults = qryResults.Where(w => w.LOCATION.CompareTo(fmVal) == 0);
}

if (!string.IsNullOrEmpty(form["ddActionLevels"]))
{
    //qryResults = qryResults.Where(w => w.PAL_ID==form["ddActionLevels"].ToString());
    vbVal = form["ddActionLevels"].ToString(); ;
    //qryResults = qryResults.Where(w => w.AL == vbVal);
    qryResults.Where(w => w.AL.CompareTo(vbVal) >= 0);
}

if (!string.IsNullOrEmpty(form["btnGenericRpt"]))
{
    qryResults.Where(w => w.LOCATION != "BB1");
}

if (!string.IsNullOrEmpty(form["ddProjects"]))
{
    vbVal = form["ddProjects"].ToString();
    qryResults.Where(w => w.PROJECT == vbVal);
}
//...
myModel.Results = qryResults.ToList();
return View(myModel);

If I only provide 1 filter, I get the data that I want. As soon as I provide more than 1 filter, I get the "Enumeration yielded no results" yet the data-set from the first filter does contain the data I am filtering on.

The main problem I see with your code is the lines like this:

qryResults.Where(w => w.AL.CompareTo(vbVal) >= 0);

You start with qryResults , compute a .Where(...) but you don't re-assign the query back to qryResults .

Try this:

qryResults = qryResults.Where(w => w.AL.CompareTo(vbVal) >= 0);

Although this doesn't explain why you're getting no results back. That'll be a question you should tackle when you get the code right.

To get filtered data and work from there I needed to add .ToList(), after Where and assign filtered results further:

class Program
{
    static void Main(string[] args)
    {
        var testList = new List<Test>()
        {
            new Test() { Field4 = false, Field1 = 19845623, Field3 = 1658006 },
            new Test() { Field4 = false, Field1 = 19845645, Field3 = 1658056 },
            new Test() { Field4 = false, Field1 = 19845665, Field3 = 1658045 },
            new Test() { Field4 = false, Field1 = 19845678, Field3 = 1658078 },
            new Test() { Field4 = false, Field1 = 19845698, Field3 = 1658098 },
        };

        var test = testList.Where(x => x.Field4 == false).ToList();
        Console.WriteLine();
    }
}

internal class Test
{
    public int Field1 { get; set; }
    public long Field3 { get; set; }
    public bool Field4 { get; set; }
}

Hope this is helpful!

Instead of doing multiple where clauses like you code exhibits, you could try using a predicatebuilder ( ref http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx ) to build the expression for your where clause based on different if statements and then use it on qryResults at the end.

Here is an example of how you can use predicateBuilder

void Main()
{
    var myQuery = new List<Car> { 
        new Car {IsRed = true, IsConvertible = true },
        new Car {IsRed = true, IsConvertible = false },
        new Car {IsRed = false, IsConvertible = true },
        new Car {IsRed = false, IsConvertible = false }
    }.AsQueryable();

    Expression<Func<Car, bool>> isRed = c => c.IsRed;
    Expression<Func<Car, bool>> isConvertible = c => c.IsConvertible;
    var isRedConvertible = isRed.And(isConvertible);

    var redConvertible = myQuery.Where(isRedConvertible);
}

public class Car
{
    public bool IsRed {get;set;}
    public bool IsConvertible {get;set;}
}

Wow, I can't believe what the problem/solution was to my issue. Because I was using the same variable (vbVal) in the .WHERE clause, when it was time to get the data, the query was using the last value of vbVal and thus not returning any data back. I'm guessing that LINQ uses ByRef for variables so my query would end up as:

vbVal = form["filter1"]; {"North America"}
qryResults = qryResults.Where (w=>w.col1 == vbVal);
vbVal = form["filter2"]; {"USA"}
qryResults = qryResults.Where (w=>w.col2 == vbVal);
vbVal = form["filter3"]; {"New York"}
qryResults = qryResults.Where (w=>w.col2 == vbVal);

The query back to SQL would be:

Select col1, col2, col3 From dbTable 
Where col1 = "New York" and col2 = "New York" and col3 = "New York"

Assigning each filter option to a unique variable solved my problem.

Thank you all for providing solutions.

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