C# 动态生成 LINQ 查询

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9505189/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 07:40:06  来源:igfitidea点击:

Dynamically generate LINQ queries

c#xmllinq

提问by P.Brian.Mackey

We have an object

我们有一个对象

public class SomeObject
{
   public Name {get;set;}
   public City {get;set;}
   public State {get;set}
   //various other parameters.  Let's say there's ~20
}

Is it possible to dynamically create new LINQ queries without recompilation of source code? Instead, the query parameters come from an XML structure that is stored and updated in the database.

是否可以在不重新编译源代码的情况下动态创建新的 LINQ 查询?相反,查询参数来自在数据库中存储和更新的 XML 结构。

var result = from i in someObj
             where 
             //XML requests Name = 'Bob'...so append this where clause
             name = 'Bob'

Can this be done?

这能做到吗?

采纳答案by Balazs Tihanyi

Here is a solution with expression trees:

这是表达式树的解决方案:

var param = Expression.Parameter(typeof(SomeObject), "p");
var exp = Expression.Lambda<Func<SomeObject, bool>>(
    Expression.Equal(
        Expression.Property(param, "Name"),
        Expression.Constant("Bob")
    ),
    param
);
var query = someObj.Where(exp);

I know it's much more complex, but this may be useful in times.

我知道它要复杂得多,但这有时可能很有用。

回答by StriplingWarrior

Yes, it's actually pretty easy:

是的,这实际上很简单:

var name = GetBobNameFromXml();
var result = someObj.Where(i => i.Name == name);

You can also choose whether or not to apply criteria piecemeal.

您还可以选择是否逐项应用标准。

var result = someObj;
var name = xmlCriteria.Name;
if(!string.IsNullOrEmpty(name))
{
    result = result.Where(i => i.Name == name);
}
// follow the same pattern for city, state, etc.

You could even use a pattern that uses a name-keyed dictionary of criterion funcs, to avoid a bunch of ifstatements.

您甚至可以使用使用标准函数的名称键字典的模式,以避免一堆if语句。

foreach(var criterionPair in xmlCriteria)
{
    var value = criterionPair.Value;
    result = result.Where(i => propGetters[criterionPair.PropertyName](i, value));
}

Basically, there's a lot you can do along these lines. If you want an answer more specifically tailored to your situation, you'll need to provide a more specific question.

基本上,您可以在这些方面做很多事情。如果您想要更适合您的情况的答案,则需要提供更具体的问题。

回答by Antineutrino

Maybe Dynamic Linq can help you: Dynamic linq part 1: Using the linq dynamic query library

也许 Dynamic Linq 可以帮助您:Dynamic linq 第 1 部分:使用 linq 动态查询库

query = query.Where("Id = 123 And Age > 18");

Or you can manipulate your Linq query directly:

或者您可以直接操作您的 Linq 查询:

query = query.Where(x=>x.Id == 5);

回答by Joachim Isaksson

You'll most certainly want to take a look at Dynamic Linqwhich will allow you to define the query conditions as text.

您肯定想看看Dynamic Linq,它允许您将查询条件定义为文本。

As for adding conditions dynamically, you can add conditions to a query using similar syntax to;

至于动态添加条件,您可以使用与以下类似的语法向查询添加条件;

if(CategoryIsImportant)
    myQuery = myQuery.Where("CategoryId=2");

all of which you can (fairly easily) encode into an XML format of your choice.

您可以(相当容易地)将所有这些编码为您选择的 XML 格式。

回答by Justin Pihony

I believe you will have to actually dig into Expression Trees. I have not dug very far into this, so I cannot create a sample for you, but I do know that you can use Expression Trees to dynamically build your queries and then call .Compile (in the code) to have it runnable.

我相信您将不得不真正深入研究表达式树。我没有深入研究这个,所以我不能为你创建一个示例,但我知道你可以使用表达式树来动态构建你的查询,然后调用 .Compile(在代码中)让它可以运行。

Actually, here is a better link Building Dynamic Queries with Expression Trees. It should give you exactly what you want, and is fairly succinct for what it is. This should act as a good example for you :)

实际上,这里有一个更好的链接Building Dynamic Queries with Expression Trees。它应该给你你想要的东西,而且相当简洁。这对你来说应该是一个很好的例子:)

回答by Douglas

I assume you want to introduce optional filters, depending on the content of your XML. To continue on the example by StriplingWarrior:

我假设您想根据 XML 的内容引入可选的过滤器。继续以 StriplingWarrior 为例:

var name = GetNameFromXml();
var city = GetCityFromXml();
var state = GetStateFromXml();

var result = someObj;
if (name != null)
    result = result.Where(i => i.Name == name);
if (city != null)
    result = result.Where(i => i.City == city);
if (state != null)
    result = result.Where(i => i.State == state);

This way, you would be applying any number of filters (from none to all three), depending on what is actually specified in your XML.

这样,您将应用任意数量的过滤器(从无到全部三个),具体取决于您的 XML 中实际指定的内容。

回答by Steve Wortham

It's hard for me to tell based on your question, but in some cases you don't need dynamic Linq and can simply do this...

根据您的问题,我很难说,但在某些情况下,您不需要动态 Linq 并且可以简单地执行此操作...

var result = from o in someObj 
             where (Name == null || o.Name == Name)
             && (City == null || o.City == City)
             && (State == null || o.State == State)
             select o;

This will essentially prevent the data from being filtered when the parameter in question is null. And it still performs well thanks to the short-circuiting behavior in C#.

当相关参数为空时,这将基本上防止数据被过滤。由于 C# 中的短路行为,它仍然表现良好。