我试图找到一种方法来构建一个where子句并将其传递给存储库Get()方法。它应该过滤名称以特定字母开头的项目。我能够构建Where 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;
}
我将不胜感激任何帮助!谢谢!
答案 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();