简体   繁体   English

动态Linq查询无法按预期工作 - 我做错了什么?

[英]Dynamic Linq query not working as expected - what am I doing wrong?

I'm trying to build a basic dynamic Linq query using LinqPad. 我正在尝试使用LinqPad构建一个基本的动态Linq查询。 My method asks users to select 1 - 3 options, and then dynamically builds the query based on their input. 我的方法要求用户选择1 - 3个选项,然后根据输入动态构建查询。

public void FilteredPropertySearch()
{
    bool addAnotherOption = true;
    int option;
    Dictionary<int, bool> parameters = new Dictionary<int, bool>();
    var predicate = PredicateBuilder.False<ResidentialProperty>();

    Console.WriteLine("Follow instructions to filter property search results");

do
{
    // get user input

    option = int.Parse(Console.ReadLine());

    switch(option)
    {
        case 1:
            parameters.Add(1, true);
            break;

    // more cases - when case 0 addAnotherOption = false, loop ends

        default:
            Console.WriteLine("That was not a valid option");
            break;
    }

}while(addAnotherOption == true);

    foreach(KeyValuePair<int, bool> p in parameters)
{   
    if(p.Key == 1 && p.Value == true)
        predicate = predicate.Or (c => c.HasBackGarden);
    if(p.Key == 2 && p.Value == true)
        predicate = predicate.Or (c => c.HasFrontGarden);
    if(p.Key == 3 && p.Value == true)
        predicate = predicate.Or (c => c.HasSecureParking);
}

ResidentialProperties.Where (predicate).Dump();

}

The foreach loop should build the query based on the user's input, but when, for example, I make the first value in the dictionary true and select no others, it doesn't return any results. foreach循环应该根据用户的输入构建查询,但是,例如,当我将字典中的第一个值设为true并且不选择其他值时,它不会返回任何结果。 It definitely should as I know there are some values in my database table that satisfy Key(1) being true. 我肯定应该知道我的数据库表中有一些值满足Key(1)是真的。

Should I be doing something else with query after the if 's in the foreach ? foreachif之后,我是否应该使用query做其他事情?

EDIT 编辑

I've used the predicate builder instead and it seems to be (kind of) working when I use predicate.Or (as per edited code), but it only returns the first option that I select, it's not building an expression tree. 我已经使用了谓词构建器,当我使用predicate.Or (根据编辑的代码)时它似乎(有点)工作,但它只返回我选择的第一个选项,它不构建表达式树。 I thought that changing predicate.Or to predicate.And would have added each selected user input to a filter expression. 我认为改变predicate.Or 。或者predicate.And并且会将每个选定的用户输入添加到过滤器表达式中。

If all three options were selected by the user, I want only rows to be returned where columns HasBackGarden, HasFrontGarden and HasSecureParking are true. 如果用户选择了所有三个选项,我只希望返回列HasBackGarden,HasFrontGarden和HasSecureParking为真的行。 How do I accomplish this? 我该如何做到这一点?

If you want to restrict your result set to those records that satisfy all of the conditions, then you are correct that you should use .And instead of .Or , but in order to do that, you need to start with PredicateBuilder.True<ResidentialProperty>() instead of False . 如果要将结果集限制为满足所有条件的那些记录,那么你应该使用.And而不是.Or是正确的,但为了做到这一点,你需要从PredicateBuilder.True<ResidentialProperty>()开始PredicateBuilder.True<ResidentialProperty>()而不是False

This is because before any filters are added, the correct result set contains all records, and each subsequent filter restricts the result set. 这是因为在添加任何过滤器之前,正确的结果集包含所有记录,并且每个后续过滤器都会限制结果集。 If you start with False , none of the records can ever possibly satisfy the predicate. 如果以False开头,则所有记录都不可能满足谓词。

From your code it looks like you are operating on the var "query" which is an empty enumerable. 从您的代码看起来您​​正在使用var“query”进行操作,这是一个空的可枚举。 Remember, what you have called query is the data set, the Where statement is the query on that data set. 请记住,您所谓的查询是数据集,Where语句是该数据集的查询。 So the first query is on an empty data set and it looks like the additional queries from the foreach will just refine that empty set. 所以第一个查询是在一个空数据集上,看起来来自foreach的其他查询只会改进那个空集。

Also, you can just do .Where(q => q.HasWhatever) since those are bools. 此外,你可以这样做。所以(q => q.HasWhatever)因为那些是bool。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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