LINQ:Foreach循环查询导致意外结果

时间:2015-06-01 18:13:39

标签: c# asp.net-mvc linq

所以我有这个查询,如果查询中有一个匹配的单词,可以返回一个记录,其中包含名字,姓氏或电话号码:

var searchWords = searchQuery
                .Split(' ')
                .Select(x => x.Trim()
                .ToLower())
                .Where(y => !string.IsNullOrWhiteSpace(y)).ToArray();

foreach (var searchWord in searchWords)
        {
            var word = searchWord;
            someParentObjects= someParentObjects
            .Where(x => x.User.FirstName.ToLower().Contains(word) ||
            x.User.LastName.ToLower().Contains(word) ||
            x.User.CellPhone.Contains(word) 
            );
        }

以某种方式包含匹配不起作用,结果我得到零结果?那是为什么?

注意:第一部分工作正常,我可以从searchQuery中获取修剪过的单词。

测试数据: 基本上我想做的就是根据查询过滤结果。如果查询中的任何单词与名字,姓氏或手机中的任何一个匹配,我将返回这些记录。所以,如果我在我的数据库中有一个记录,其名字是" James"姓氏是#34; Brian",如果我将查询作为" James Something"它应该返回一个记录。但它没有回归。我得到零记录。

4 个答案:

答案 0 :(得分:1)

您的代码基本上过滤了所有“searchWords”,以便至少出现在其中一个字段中。最有可能是多个单词,这样的过滤不会返回任何结果。

搜索字词“Bob John”和患者“John Doe”foreach的简化版本:

var filtered = new[]{"John"}
 .Where(firstName => firstName.Contains("Bob"))
 .Where(firstName => firstName.Contains("John"));

虽然目前还不清楚你在寻找什么,但可能停在第一个非空结果上是一个选项:

    foreach (var searchWord in searchWords)
    {
        var word = searchWord;
        var filteredPatientSteps = patientSteps
        .Where(x => x.User.FirstName.ToLower().Contains(word) ||
        x.User.LastName.ToLower().Contains(word) ||
        x.User.CellPhone.Contains(word) 
        );
        if (filteredPatientSteps.Any())
        {
             // jump out on first match 
            patientSteps = filteredPatientSteps;
            break;
         }
    }

答案 1 :(得分:1)

你得到"詹姆斯"在你的searchWords数组?你的代码似乎没问题。如果searchQuery包含像" James John Doe"那么searchWords的第一个元素就是"詹姆斯"其余的似乎很好。我已经厌倦了:

YES

我将User和Parent视为:

var searchQuery = "John Doe Brazil";

            var searchWords = searchQuery
                .Split(' ')
                .Select(x => x.Trim()
                    .ToLower())
                .Where(y => !string.IsNullOrWhiteSpace(y)).ToArray();
            User obj=new User()
            {
                FirstName = "Ali",
                LastName = "John"
            };
            var someParentObjects =new[]{ new Parent(){Users =obj}};


            foreach (var searchWord in searchWords)
            {
                var word = searchWord;
              var ParentObjects = someParentObjects
                .Where(x => x.Users.FirstName.ToLower().Contains(word) ||
                x.Users
                .LastName.ToLower().Contains(word) 

                );
            }

在这种情况下,ParentObjects返回对象Ali John。

修改 要使用ParentObjects外部循环,请执行以下操作:

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Parent
{
    public User Users { get; set; }
    public Parent() { }

}

然后可以在循环外使用ParentObjects。

答案 2 :(得分:1)

使用foreach循环包装linq语句通常表示出现了问题。 Linq已经为你做了“循环”部分。

var searchWords = searchQuery
                .Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries)
                .Select(x => x.Trim().ToUpper())
                .ToArray();

在这里,我们将搜索逻辑反转为使用包含Any(),Linq为我们处理枚举。

var result = (from step in patientSteps
              where searchWords.Any(x => 
              step.User.FirstName.ToUpper().Contains(x) ||
              step.User.LastName.ToUpper().Contains(x) ||
              step.User.CellPhone.Contains(x) )
              select step);

答案 3 :(得分:0)

您还没有足够的资源来创建复制品,但如果我填写剩下的部分,您的现有代码似乎也能正常工作。

void Main() {
    string searchQuery = "foo bar";
    IEnumerable<PatientStep> patientSteps = new PatientStep[] {
        new PatientStep("foo", "bar", "12345"),
        new PatientStep("foo", "williams", "12345"),
        new PatientStep("nancy", "bar", "12345"),
        new PatientStep("nothing", "relevant", "12345"),
    };

    var searchWords = searchQuery
                    .Split(' ')
                    .Select(x => x.Trim()
                        .ToLower())
                    .Where(y => !string.IsNullOrWhiteSpace(y)).ToArray();

    foreach (var searchWord in searchWords) {
        var word = searchWord;
        patientSteps = patientSteps.Where(
            x => x.User.FirstName.ToLower().Contains(word)
                || x.User.LastName.ToLower().Contains(word)
                || x.User.CellPhone.Contains(word)
        );
    }

    foreach (var patientStep in patientSteps) {
        Console.WriteLine(patientStep.ToString());
    }
}

class PatientStep {
    public User User { get; private set; }

    public PatientStep(string first, string last, string cell) {
        this.User = new User { FirstName = first, LastName = last, CellPhone = cell };
    }

    public override string ToString() {
        return string.Format("{0} {1}, {2}", this.User.FirstName, this.User.LastName, this.User.CellPhone);
    }
}

class User {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string CellPhone { get; set; }
}

这会产生输出:

foo bar, 12345