Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 构建一个Linq到EF查询,以在一个可变列数的关键字的可变列表中进行查询?_C#_Entity Framework_Linq_Predicatebuilder - Fatal编程技术网

C# 构建一个Linq到EF查询,以在一个可变列数的关键字的可变列表中进行查询?

C# 构建一个Linq到EF查询,以在一个可变列数的关键字的可变列表中进行查询?,c#,entity-framework,linq,predicatebuilder,C#,Entity Framework,Linq,Predicatebuilder,我试图提出一种实用方法来构建Linq查询或Linq谓词,将其添加到Linq to EF查询中,以便在可变列数的术语列表中搜索所有术语 我正在尝试使用PredicateBuilder构建where子句。有了一个搜索词和一个固定的列列表,这就相对容易了。 到目前为止,我尝试编写的伪代码如下所示: private static Predicate<Project> CreateDynamicSearch(IEnumerable<strings> searchableColumn

我试图提出一种实用方法来构建Linq查询或Linq谓词,将其添加到Linq to EF查询中,以便在可变列数的术语列表中搜索所有术语

我正在尝试使用PredicateBuilder构建where子句。有了一个搜索词和一个固定的列列表,这就相对容易了。 到目前为止,我尝试编写的伪代码如下所示:

private static Predicate<Project> CreateDynamicSearch(IEnumerable<strings> searchableColumns, string[] searchTerms)
{
      var predicate = PredicateBuilder.True<Project>();
      foreach (var columnName in searchableColumns) 
      { 
        foreach (var term in searchTerms)
        {
          predicate = predicate.And(a => a.**columnName**.Contains(term));
        }
       predicate = predicate.Or(predicate);
      }
      return predicate;
}
私有静态谓词CreateDynamicSearch(IEnumerable searchableColumns,string[]searchTerms)
{
var predicate=PredicateBuilder.True();
foreach(searchableColumns中的变量columnName)
{ 
foreach(搜索术语中的var术语)
{
谓词=谓词。和(a=>a.*columnName**.Contains(term));
}
谓词=谓词。或(谓词);
}
返回谓词;
}
我遇到的最大问题是如何处理列名的表达式。之前的建议是使用表达式树,但我不明白这在这个场景中是如何工作的

**更新** 更新后,我接受了您的代码。它生成,但当我在Extension.Property(param,columnName)上实际调用时出错line,错误为未为类型“System.Func`2[Myclass,System.Boolean]”消息定义实例属性“Name”。columnName=“Name”

**更新2** 它被称为:

var test = CreateDynamicSearch<Func<Project, bool>>(searchCols, searchTerms);
var test=CreateDynamicSearch(searchCols,searchTerms);

您可以自己构建谓词表达式,在这种情况下,它相对简单:

private static Expression<Func<T, bool>> CreateDynamicSearch<T>(IEnumerable<string> searchableColumns, string[] searchTerms) {
    // start with true, since we combine with AND
    // and true AND anything is the same as just anything
    var predicate = PredicateBuilder.True<T>();
    foreach (var columnName in searchableColumns) {                
        // start with false, because we combine with OR
        // and false OR anything is the same as just anything
        var columnFilter = PredicateBuilder.False<T>();
        foreach (var term in searchTerms) {
            // a =>
            var param = Expression.Parameter(typeof(T), "a");
            // a => a.ColumnName
            var prop = Expression.Property(param, columnName);
            // a => a.ColumnName.Contains(term)
            var call = Expression.Call(prop, "Contains", new Type[0], Expression.Constant(term));
            columnFilter = columnFilter.Or(Expression.Lambda<Func<T, bool>>(call, param));
        }
        predicate = predicate.And(columnFilter);
    }
    return predicate;
}
私有静态表达式CreateDynamicSearch(IEnumerable searchableColumns,string[]searchTerms){
//从true开始,因为我们结合了和
//这是真的,任何事情都是一样的
var predicate=PredicateBuilder.True();
foreach(searchableColumns中的var columnName){
//从false开始,因为我们结合了OR
//虚假或任何东西都是一样的
var columnFilter=PredicateBuilder.False();
foreach(搜索术语中的var术语){
//a=>
var param=表达式参数(类型(T),“a”);
//a=>a.ColumnName
var prop=Expression.Property(param,columnName);
//a=>a.ColumnName.Contains(术语)
var call=Expression.call(prop,“Contains”,新类型[0],Expression.Constant(term));
columnFilter=columnFilter.Or(Expression.Lambda(call,param));
}
谓词=谓词和(列过滤器);
}
返回谓词;
}
回应评论

我只是想知道你是否有办法把 由expression.Property(param,columnName)创建的表达式 编译器为(字符串s)->s.Contains(术语)生成的一个

您可以这样做(例如):

// a =>
var param = Expression.Parameter(typeof(T), "a");                    
// a => a.ColumnName
var prop = Expression.Property(param, columnName);                    
// s => s.Contains(term)
Expression<Func<string, bool>> contains = (string s) => s.Contains(term);
// extract body - s.Contains(term)
var containsBody = (MethodCallExpression)contains.Body;                    
// replace "s" parameter with our property - a.ColumnName.Contains(term)
// Update accepts new target as first parameter (old target in this case is 
// "s" parameter and new target is "a.ColumnName")
// and list of arguments (in this case it's "term" - we don't need to update that).
// 
var call = containsBody.Update(prop, containsBody.Arguments);
columnFilter = columnFilter.Or(Expression.Lambda<Func<T, bool>>(call, param));
//a=>
var param=表达式参数(类型(T),“a”);
//a=>a.ColumnName
var prop=Expression.Property(param,columnName);
//s=>s.Contains(术语)
表达式contains=(字符串s)=>s.contains(术语);
//提取物主体-s.Contains(术语)
var containsBody=(MethodCallExpression)contains.Body;
//将“s”参数替换为我们的属性-a.ColumnName.Contains(术语)
//更新接受新目标作为第一个参数(在本例中,旧目标为
//“s”参数,新目标为“a.ColumnName”)
//和参数列表(在本例中是“术语”-我们不需要更新它)。
// 
var调用=containsBody.Update(prop,containsBody.Arguments);
columnFilter=columnFilter.Or(Expression.Lambda(call,param));

您的代码非常独特<代码>谓词=谓词。或(谓词)没有任何意义。我们的想法是在记录的某个地方找到所有包含所有搜索词的记录。i、 e.Firstname Lastname=John&smith如果这是您想要的,恐怕您确实需要创建自己的表达式树。但您也可以轻松地构建自己的SQL表达式(前提是不需要将LINQ查询与非SQL数据存储一起使用)。但是,无论哪种方式,您的示例中都有一个逻辑错误,您需要一个临时变量来为每个列构建“和”列表,然后您可以将其与现有的谓词变量组合。@JohnS我更新了答案,因为条件是混合的(因为在您的帖子中它们是混合的:)。您需要将
Contains
与或(因为match是指列包含任何提供的术语)连接起来,并将它们与and连接起来,因为match是指所有提供的列都满足条件。添加了我现在得到的错误。有什么想法吗?@JohnS你能包括你如何调用该方法吗?@JohnS从错误中可以看出你调用它就像
CreateDynamicSearch()
但是你只需要
CreateDynamicSearch
@JohnS,我在上面写了调用中的错误:)你基本上多次调用
Expression.Property
Expression.Property(Expression.Property(param,navigationPropertyName),columnOfIncludedEntity))
。如果嵌套级别未知,则使用循环。好吧,我希望你自己能弄明白:)