LINQ 中的动态 where 子句 - 列名在运行时可用

发布于 2024-07-08 01:38:40 字数 500 浏览 8 评论 0原文

免责声明:我已经使用 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。

Disclaimer: I've solved the problem using Expressions from System.Linq.Expressions, but I'm still looking for a better/easier way.

Consider the following situation :

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

The columns/attributes that need to be checked against the blacklisted term are only available to me at runtime. How do I generate this dynamic where clause?

An additional complication is that the Queryable collection (db.Customers above) is typed to a Queryable of the base class of 'Customer' (say 'Person'), and therefore writing c.Address as above is not an option.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

请帮我爱他 2024-07-15 01:38:40

@Geoff 有最好的选择,就是 Dynamic 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。

@Geoff has the best option, justing Dynamic LINQ.

If you want to go the way of building queries at runtime using Lambda though I'd recomment that you use the PredicateBuilder (http://www.albahari.com/nutshell/predicatebuilder.aspx) and have something such as this:

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
  }
}

And so on for all the columns you want to include. When you get to your query you just need something like this:

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

I've used this to do building of LINQ for searching where there are about 20 different options and it produces really good SQL.

在你怀里撒娇 2024-07-15 01:38:40
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"));

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

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

Note that they aren't mutually exclusive.

生生漫 2024-07-15 01:38:40

您可以使用一些逻辑表达式打开和关闭 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为true,则or语句另一侧的条件将被忽略。

You can turn your where clauses on and off using some logic expressions.

//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;  

If ignoreFirstName is true in the query then the condition on the other side of the or statement will be ignored.

回眸一遍 2024-07-15 01:38:40

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

Since this is not LINQ to Objects, but rather LINQ to SQL, you have no other alternative beside using either Expressions or a stored procedure.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文