我遇到了麻烦,无法弄清楚似乎是一件非常简单的事情,在普通SQL中可以在1分钟内完成,到目前为止已经几个小时了。情况如下:
- 我有一个字段,用户可以输入尽可能多的单词,因为他/她喜欢
- 我需要构建表达式来查找匹配
- 假设数据库中有3个字段:名,名,姓
- 我需要拆分搜索条目并与这3个字段进行比较
- 我正在处理Silverlight RIA, EF
- 再次搜索条目包含未知数量的单词
在我想要完成的下面,返回类型是强制性的:
public Expression<Func<MyEntity, bool>> GetSearchExpression(string text)
{
Expression<Func<MyEntity, bool>> result;
var keywords = text.Trim().Split(" ");
foreach(var keyword in keywords)
{
// TODO:
// check whether 'OR' is required (i.e. after second loop)
// (firstname = 'keyword'
// AND
// middlename = 'keyword'
// AND
// lastname = 'keyword')
// OR
// (firstname like '%keyword%'
// AND
// middlename like '%keyword%'
// AND
// lastname like '%keyword%')
}
return result;
}
提前感谢!
最简单的方法是使用Joe Albahari的PredicateBuilder来做这样的事情:
var predicate = PredicateBuilder.False<MyEntity>();
foreach (string keyword in keywords)
{
string temp = keyword;
predicate = predicate.Or (
p => p.FirstName.Contains (temp) &&
p.LastName.Contains (temp) &&
p.MiddleName.Contains (temp));
}
return predicate;
我省略了相等性检查,因为"Contains"(即like '%...%'
)无论如何都会涵盖这种可能性。
但是,我必须指出,从业务逻辑的角度来看,您的条件没有任何意义。在什么情况下,你想找一个名字、姓氏和中间名都包含"约翰"的人?我怀疑你真正想要的是这样的东西:
var predicate = PredicateBuilder.True<MyEntity>();
foreach (string keyword in keywords)
{
string temp = keyword;
predicate = predicate.And (
p => p.FirstName.Contains (temp) ||
p.LastName.Contains (temp) ||
p.MiddleName.Contains (temp));
}
return predicate;
最后一个注意事项:因为PredicateBuilder要求您在创建查询时调用.AsExpandable()
,我不知道这是否适合您。您可能不得不求助于构建自己的表达式,这可能有点乏味。这可以让你开始:
var pParam = Expression.Parameter(typeof(MyEntity), "p");
var predicate = Expression.Constant(true);
foreach (string keyword in keywords)
{
var keywordExpr = Expression.Constant(keyword);
// TODO: create an expression to invoke .FirstName getter
// TODO: create an expression to invoke string.Contains() method
//TODO: do the same for lastname and middlename
predicate = Expression.And(predicate,
Expression.Or(
Expression.Or(firstNameContainsKeyword,
middleNameContainsKeyword),
lastNameContainsKeyword));
}
return Expression.Lambda<Func<MyEntity, bool>>(predicate, pParam);