构建where子句体

时间:2015-04-16 13:35:29

标签: c# linq entity-framework collections

我试图找到一种方法来构建一个where子句并将其传递给存储库Get()方法。它应该过滤名称以特定字母开头的项目。我能够构建Where Where子句体的一部分,但是找不到如何处理项目名称不以字母开头的方案的方法。例如:_ItemName97_SomeName

所以,这是我的方法:

protected override Expression<Func<DataSetSettings, bool>> GetWhereClause()
{
    //The user has selected FilterLetter, for example: "A"
    // return all items which name starts with "A"
    if (!string.IsNullOrWhiteSpace(FilterLetter) && !FilterLetter.Equals("All"))
        return (x => x.Name.StartsWith(FilterLetter) && x.Type == Type);

    if (FilterLetter.Equals("Other"))
    {
        //Here i need to extract all items which name does not start with letter
    }

    //return All items of the current type
    return x => x.Type == Type;
}

我将不胜感激任何帮助!谢谢!

3 个答案:

答案 0 :(得分:1)

你可以在你的StartsWith上做等于假的

像这样:

return (x => x.Name.StartsWith(FilterLetter) == false && x.Type == Type);

答案 1 :(得分:1)

既然我明白了你的需要,我环顾四周,无法找到一个优雅的解决方案。似乎复杂的字符串模式匹配是EF中的一个弱点。

我能看到这样做的唯一方法是与每个字母进行比较,即:

!x.Name.StartsWith("A") && !x.Name.StartsWith("B") && //on and on to Z

或者确保将整个列表加载到内存中,然后使用正则表达式进行过滤:

protected override Expression<Func<DataSetSettings, bool>> GetWhereClause()
{
    var noletter = new Regex("^[^a-z].*", RegexOptions.IgnoreCase);

    return (
        x => x.Type == Type && (
            string.IsNullOrWhiteSpace(FilterLetter) || 
            FilterLetter == "All" || 
            (FilterType == "Other" && noletter.IsMatch(x.Name)) ||
            x.Name.StartsWith(FilterType)
        )
    );
}

如果您最终选择将所有内容加载到内存中,则至少可以先基于x.Type进行过滤。这似乎是过滤的共同点。至少在这种情况下,您不必将整个表加载到内存中。

答案 2 :(得分:0)

我的建议是将所有类型的1 db调用放入列表中,然后使用linq查询该列表。你的例子是进行两次db调用。

List<Type> allTypes = new List<Type>();
List<Type> typesWithA = new List<Type>();
List<Type> typesWOA = new List<Type>();

// make one db call
allTypes = entities.Types.ToList();

typesWithA = allTypes.Where(x => x.Name.StartsWith(FilterLetter)).ToList();
typesWOA = allTypes.Where(x => !x.Name.StartsWith(FilterLetter)).ToList();