C# 在LinqToEntities中,如何将动态列名传递给DbFunctions.Like

C# 在LinqToEntities中,如何将动态列名传递给DbFunctions.Like,c#,entity-framework-6,linq-to-entities,iqueryable,linq-expressions,C#,Entity Framework 6,Linq To Entities,Iqueryable,Linq Expressions,我在实体框架中的DbSet中有一个IQueryable。我收到一个名为searchText的“模糊搜索字符串”,如下所示: public List<T> Search<T>(string searchText) { using (var context = ...) { var baseQuery = context.Set<T>().AsQueryable(); baseQuery = baseQuery.Wh

我在实体框架中的
DbSet
中有一个
IQueryable
。我收到一个名为
searchText
的“模糊搜索字符串”,如下所示:

public List<T> Search<T>(string searchText)
{
    using (var context = ...)
    {
        var baseQuery = context.Set<T>().AsQueryable();
        baseQuery = baseQuery.Where(x =>
            DbFunctions.Like(x.PropertyName, searchText)
            || DbFunctions.Like(x.PropertyTwo, searchText)
            || DbFunctions.Like(x.PropertyThree, searchText)
            || DbFunctio..... etc
        );
        return baseQuery.ToList();
    }
}

这里的问题是。。。嗯,一开始它不起作用。但主要是我没有在任何地方使用
searchText
,也不知道如何插入它。我想我很接近。。。但是我在这上面花费了大量的时间。

希望我正确地理解了您的查询逻辑:如果您想基于已知类型和列名列表构建一组类似于的条件,您可以尝试以下方法:

static private MethodInfo dbLikeMethod = typeof(DbFunctions).GetMethod(nameof(DbFunctions.Like), BindingFlags.Public | BindingFlags.Static, null, new Type[] {typeof(string), typeof(string)}, null); // I am targeting DbFunctions.Like(string, string). You might want another overload (or even mix them up depending on your inputs)

public List<T> Search<T>(string searchText) where T: class
{

    using (var context = new ...)
    {
        var baseQuery = context.Set<T>().AsQueryable().Where(CreateExpression<T>(searchText));// you could probably find a more elegant way of plugging it into your query
        return baseQuery.ToList();
    }
}

Expression<Func<T, bool>> CreateExpression<T>(string searchText) where T : class
{   
    var cols = new List<string> {
        "PropertyName",
        "PropertyTwo" // i understand you've got a way to figure out which strings you need here
    };

    var parameter = Expression.Parameter(typeof(T), "x");   
    var dbLikeCalls = cols.Select(colName => Expression.Call(dbLikeMethod, Expression.PropertyOrField(parameter, colName), Expression.Constant(searchText))); // for convenience, generate list of DbFunctions.Like(x.<Property>, searchText) expressions here
    var aggregatedCalls = dbLikeCalls.Skip(1).Aggregate((Expression)dbLikeCalls.First(), (accumulate, call) => Expression.OrElse(accumulate, call)); // aggregate the list using || operators: use first item as a seed and keep adding onto it

    return Expression.Lambda<Func<T, bool>>(aggregatedCalls, parameter);
}
static private MethodInfo dbLikeMethod=typeof(DbFunctions).GetMethod(nameof(DbFunctions.Like),BindingFlags.Public | BindingFlags.static,null,new Type[]{typeof(string),typeof(string)},null);//我的目标是DbFunctions.Like(string,string)。您可能需要另一个重载(甚至根据您的输入将它们混合在一起)
公共列表搜索(字符串搜索文本),其中T:class
{
使用(var context=new…)
{
var baseQuery=context.Set().AsQueryable().Where(CreateExpression(searchText));//您可能会找到一种更优雅的方法将其插入查询中
返回baseQuery.ToList();
}
}
表达式CreateExpression(字符串搜索文本),其中T:class
{   
var cols=新列表{
“PropertyName”,
“PropertyTwo”//我知道您已经找到了一种方法来确定此处需要哪些字符串
};
var参数=表达式参数(类型为(T),“x”);
var dbLikeCalls=cols.Select(colName=>Expression.Call(dbLikeMethod,Expression.PropertyOrField(参数,colName),Expression.Constant(searchText));//为方便起见,在此处生成DbFunctions.Like(x,searchText)表达式列表
var aggregatedCalls=dbLikeCalls.Skip(1).Aggregate((表达式)dbLikeCalls.First(),(累计,调用)=>Expression.OrElse(累计,调用));//使用| |运算符聚合列表:将第一项用作种子并不断添加到其中
返回表达式.Lambda(aggregatedCalls,参数);
}
static private MethodInfo dbLikeMethod = typeof(DbFunctions).GetMethod(nameof(DbFunctions.Like), BindingFlags.Public | BindingFlags.Static, null, new Type[] {typeof(string), typeof(string)}, null); // I am targeting DbFunctions.Like(string, string). You might want another overload (or even mix them up depending on your inputs)

public List<T> Search<T>(string searchText) where T: class
{

    using (var context = new ...)
    {
        var baseQuery = context.Set<T>().AsQueryable().Where(CreateExpression<T>(searchText));// you could probably find a more elegant way of plugging it into your query
        return baseQuery.ToList();
    }
}

Expression<Func<T, bool>> CreateExpression<T>(string searchText) where T : class
{   
    var cols = new List<string> {
        "PropertyName",
        "PropertyTwo" // i understand you've got a way to figure out which strings you need here
    };

    var parameter = Expression.Parameter(typeof(T), "x");   
    var dbLikeCalls = cols.Select(colName => Expression.Call(dbLikeMethod, Expression.PropertyOrField(parameter, colName), Expression.Constant(searchText))); // for convenience, generate list of DbFunctions.Like(x.<Property>, searchText) expressions here
    var aggregatedCalls = dbLikeCalls.Skip(1).Aggregate((Expression)dbLikeCalls.First(), (accumulate, call) => Expression.OrElse(accumulate, call)); // aggregate the list using || operators: use first item as a seed and keep adding onto it

    return Expression.Lambda<Func<T, bool>>(aggregatedCalls, parameter);
}