构建 where 子句主体
Build where clause body
我正在尝试找到一种方法来构建 where 子句并将其传递给存储库 Get() 方法。它应该过滤名称以特定字母开头的项目。我能够构建此 Where 子句正文的一部分,但无法找到一种方法来处理项目名称不以字母开头的情况。例如:_ItemName
或 97_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 加载到内存中。
我正在尝试找到一种方法来构建 where 子句并将其传递给存储库 Get() 方法。它应该过滤名称以特定字母开头的项目。我能够构建此 Where 子句正文的一部分,但无法找到一种方法来处理项目名称不以字母开头的情况。例如:_ItemName
或 97_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 加载到内存中。