如何在linq where子句中使用函数的返回值?

时间:2012-11-30 17:11:19

标签: c# linq

我正在尝试针对EF实体类型(人)创建常规搜索查询。通常,搜索采用字符串,用逗号分隔,然后搜索各种属性包含所有关键字的人。

我有一个名为getProperties(Person p)的函数,它接受一个实体(由实体类型覆盖),并返回一个用分隔符连接在一起的各种相关属性的字符串......例如:

John~Doe~Team A~Full Time

如果用户搜索“Team A,Full”,则应返回与上述展平实体相对应的人...但是,如果输入“John,Smith”则不应该返回。

我认为以下情况看起来正确,但它不起作用......

public IEnumerable<Person> SearchPeople(string searchString)
{
    if (searchString == null || string.IsNullOrEmpty(searchString.Trim()))
        return base._objectSet.ToList();

    string[] SearchWords = searchString.Split(',').Select(s => s.Trim()).ToArray();

    return (from    person 
            in      base._objectSet 
            let     t = (getProperties(person)) 
            where   SearchWords.All(word => t.Contains(word)) 
            select  person).ToList();
}

并且getProperties函数是:

public static string getProperties(Person p)
{
    string[] values = { p.Surname, p.GivenName, p.Team, p.Status };
    return values.Aggregate((x, y) => String.IsNullOrEmpty(y) ? x : string.Concat(x, "~", y));
}

有谁知道我哪里出错了?

修改

没有引发异常,但是当我单步执行代码时,当我到达linq时,它会进入托管查询的unitofwork的dispose方法。很奇怪。

如果我更改它以便搜索硬编码的字符串,它会按预期工作:

var test = (from    person 
            in      base._objectSet 
            where   SearchWords.All(word => "John~Doe~Team A~Full Time".Contains(word))
            select person).ToList();

嗯,它的作用是它匹配我期望的查询,但因为它是静态的,它返回每个人的记录(非常像在哪里(true)= P)

编辑第二个

甚至更奇怪的是,如果我将结果存储到var中,然后在返回时返回带有断点的var,执行永远不会到达断点...这个linq就像一个黑洞...我可以进入它,但它永远不会让我回到我的SearchPeople方法......它只是处理上下文并忘记它。

编辑第三个

如果我不立即调用ToString()并查看调试器中的linq表达式,它会说“Linq to Entities无法识别方法getProperties(Person)”看起来它在我的方法上默默地窒息..任何方式使用我的方法没有linq choking它?

2 个答案:

答案 0 :(得分:0)

您要退回一份清单吗?尝试将返回类型设为列表或将.ToList()更改为AsEnumerable()

public List<Person> SearchPeople(string searchString)
{
    if (searchString == null || string.IsNullOrEmpty(searchString.Trim()))
        return base._objectSet.ToList();

    string[] SearchWords = searchString.Split(',').Select(s => s.Trim()).ToArray();

    return (from    person 
            in      base._objectSet 
            let     t = (getProperties(person)) 
            where   SearchWords.All(word => t.Contains(word)) 
            select  person).ToList();
}

答案 1 :(得分:0)

好吧,在发现linq 2 entites不喜欢方法之后(因为不知道如何将它翻译成sql),我重写了我的linq是一种非常乏味但功能正常的方式:

var people = from    p
             in      base._objectSet
             where   SearchWords.All(p.GivenName.Contains(word) || p.Surname.Contains(word) || p.(???).Contains(word) || etc.)
                    select p;

烦人,但你去了。