构建 where 子句主体

Build where clause body

我正在尝试找到一种方法来构建 where 子句并将其传递给存储库 Get() 方法。它应该过滤名称以特定字母开头的项目。我能够构建此 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;
}

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

您可以在 StartsWith

上做 equals false

像这样:

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

我的建议是将所有类型的 1 db 调用放入一个列表中,然后使用 linq 查询该列表。您的示例将进行两次数据库调用。

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();

既然我明白了你的需要,我环顾四周,但没能找到一个优雅的解决方案。似乎复杂的字符串模式匹配是 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 进行过滤。这似乎是过滤的共同点。至少这样你就不必将整个 table 加载到内存中。