C# 通用 LINQ 查询谓词?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/125400/
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-03 14:44:20  来源:igfitidea点击:

Generic LINQ query predicate?

提问by Codewerks

Not sure if this is possible or if I'm expressing correctly what I'm looking for, but I have the following piece of code in my library repeatedly and would like to practice some DRY. I have set of SQL Server tables that I'm querying based on a simple user-supplied search field ala Google. I'm using LINQ to compose the final query based on what's in the search string. I'm looking for a way to use generics and passed in lambda functions to create a reusable routine out of this:

不确定这是否可行,或者我是否正确表达了我正在寻找的内容,但是我的库中反复有以下代码段,并且想练习一些 DRY。我有一组 SQL Server 表,我根据用户提供的简单搜索字段 ala Google 查询这些表。我正在使用 LINQ 根据搜索字符串中的内容编写最终查询。我正在寻找一种方法来使用泛型并传入 lambda 函数来创建一个可重用的例程:

string[] arrayOfQueryTerms = getsTheArray();

var somequery = from q in dataContext.MyTable
                select q;

if (arrayOfQueryTerms.Length == 1)
{
    somequery = somequery.Where<MyTableEntity>(
        e => e.FieldName.StartsWith(arrayOfQueryTerms[0]));
}
else
{
    foreach(string queryTerm in arrayOfQueryTerms)
    {
        if (!String.IsNullOrEmpty(queryTerm))
        {
            somequery = somequery 
                        .Where<MyTableEntity>(
                            e => e.FieldName.Contains(queryTerm));
        }
    }
}

I was hoping to create a generic method with signature that looks something like:

我希望创建一个带有签名的通用方法,如下所示:

private IQueryable<T> getQuery(
    T MyTableEntity, string[] arrayOfQueryTerms, Func<T, bool> predicate)

I'm using the same search strategy across all my tables, so the only thing that really differs from usage to usage is the MyTable & MyTableEntity searched and the FieldName searched. Does this make sense? Is there a way with LINQ to dynamically pass in the name of the field to query in the where clause? Or can I pass in this as a predicate lambda?

我在我的所有表中使用相同的搜索策略,因此唯一不同的用法是搜索的 MyTable 和 MyTableEntity 以及搜索的 FieldName。这有意义吗?LINQ 有没有办法动态传入字段名称以在 where 子句中查询?或者我可以将其作为谓词 lambda 传入?

e => e.FieldName.Contains(queryTerm)

I realize there a million and a half ways to do this in SQL, probably easier, but I'd love to keep everything in the LINQ family for this one. Also, I feel that generics should be handy for a problem like this. Any ideas?

我意识到在 SQL 中有一百万种半方法可以做到这一点,可能更容易,但我很想为这个保留 LINQ 系列中的所有内容。另外,我觉得泛型应该很方便解决这样的问题。有任何想法吗?

采纳答案by Erik Forbes

It sounds like you're looking for Dynamic Linq. Take a look here. This allows you to pass strings as arguments to the query methods, like:

听起来您正在寻找 Dynamic Linq。看看这里。这允许您将字符串作为参数传递给查询方法,例如:

var query = dataSource.Where("CategoryID == 2 && UnitPrice > 3")
                      .OrderBy("SupplierID");

Edit: Another set of posts on this subject, using C# 4's Dynamic support: Part 1and Part 2.

编辑:关于此主题的另一组帖子,使用 C# 4 的动态支持:第 1部分第 2 部分

回答by Quintin Robinson

What it sounds like is you want basically a conditional predicate builder..

听起来您基本上想要一个条件谓词构建器..

I hope you can mold this into something you are looking for, good luck!

我希望你能把它塑造成你正在寻找的东西,祝你好运!

http://www.albahari.com/nutshell/predicatebuilder.aspx

http://www.albahari.com/nutshell/predicatebuilder.aspx

回答by Mark Cidade

You might want to look at expression trees:

您可能想查看表达式树:

IQueryable<T> getQuery<T>(T myTableEntity, string[] arrayOfQueryTerms, Expression<Func<T, bool>> predicate)
 { var fieldOrProperty = getMemberInfo(predicate);
   /* ... */
 }

MemberInfo getmemberInfo<T>(Expression<Func<T,bool> expr)
 { var memberExpr = expr as MemberExpression;
   if (memberExpr != null) return memberExpr.Member;
   throw new ArgumentException();
 }

var q = getQuery<FooTable>(foo, new[]{"Bar","Baz"}, x=>x.FieldName);

回答by user17060

I recently had to do this same thing. You will need Dynamic Linqhereis a way to keep this strongly typed.

我最近不得不做同样的事情。您将需要Dynamic Linq,是一种保持强类型的方法。