9

免责声明:我已经使用 System.Linq.Expressions 中的表达式解决了这个问题,但我仍在寻找更好/更简单的方法。

考虑以下情况:

var query = 
    from c in db.Customers
    where (c.ContactFirstName.Contains("BlackListed") || 
           c.ContactLastName.Contains("BlackListed")  ||
           c.Address.Contains("BlackListed"))
    select c;

需要对照列入黑名单的术语检查的列/属性仅在运行时对我可用。如何生成此动态 where 子句?

另一个复杂情况是 Queryable 集合(上面的 db.Customers)被输入到基类“Customer”(比如“Person”)的 Queryable 中,因此不能像上面那样编写 c.Address。

4

4 回答 4

13

@Geoff 有最好的选择,只是动态 LINQ。

如果您想在运行时使用 Lambda 构建查询,但我建议您使用 PredicateBuilder ( http://www.albahari.com/nutshell/predicatebuilder.aspx ) 并具有以下内容:

Expression<Fun<T,bool>> pred = null; //delcare the predicate to start with. Note - I don't know your type so I just used T 
if(blacklistFirstName){
  pred = p => p.ContactFirstName.Contains("Blacklisted");
}
if(blacklistLastName){
  if(pred == null){
    pred = p => p.ContactLastName.Contains("Blacklisted"); //if it doesn't exist just assign it
  }else{
    pred = pred.And(p => p.ContactLastName.Contains("Blacklisted"); //otherwise we add it as an And clause
  }
}

对于您要包含的所有列,依此类推。当您进行查询时,您只需要以下内容:

var results = db.Customers.Where(pred).Select(c => c);

我用它来构建 LINQ 以搜索大约 20 种不同选项的位置,它会产生非常好的 SQL。

于 2008-10-25T22:30:42.783 回答
8
var query = from C in db.Customers select c;

if (seachFirstName)
         query = query.Where(c=>c.ContactFirstname.Contains("Blacklisted"));

if (seachLastName)
         query = query.Where(c=>c.ContactLastname.Contains("Blacklisted"));

if (seachAddress)
         query = query.Where(c=>c.Address.Contains("Blacklisted"));

请注意,它们不是相互排斥的。

于 2008-10-24T17:35:45.913 回答
2

您可以使用一些逻辑表达式打开和关闭 where 子句。

//Turn on all where clauses
bool ignoreFirstName = false;
bool ignoreLastName = false;;
bool ignoreAddress = false;

//Decide which WHERE clauses we are going to turn off because of something.
if(something)
    ignoreFirstName = true; 

//Create the query
var queryCustomers = from c in db.Customers 
    where (ignoreFirstName || (c.ContactFirstName.Contains("BlackListed")))
    where (ignoreLastName || (c.ContactLastName.Contains("BlackListed")))
    where (ignoreAddress || (c.Address.Contains("BlackListed"))
    select j;  

如果在查询中 ignoreFirstName 为真,则 or 语句另一侧的条件将被忽略。

于 2012-03-01T12:14:10.180 回答
0

由于这不是 LINQ to Objects,而是 LINQ to SQL,因此除了使用表达式或存储过程之外,您别无选择。

于 2008-10-25T22:19:59.357 回答