Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.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
如何在实体框架、扩展方法中为客户使用谓词,其中LINQ查询;“按文字搜索”;_Linq_Search_Where_Predicate - Fatal编程技术网

如何在实体框架、扩展方法中为客户使用谓词,其中LINQ查询;“按文字搜索”;

如何在实体框架、扩展方法中为客户使用谓词,其中LINQ查询;“按文字搜索”;,linq,search,where,predicate,Linq,Search,Where,Predicate,我想使用谓词构建一个自定义linq查询 而不是使用静态Where子句,即 public IEnumerable<Entities.BusinessDirectory.BDEntity> Search(string searchExpression) { var db = new ApplicationDbContext(); return db.BDEntities .Where(x => searchExpression.Split(

我想使用谓词构建一个自定义linq查询

而不是使用静态
Where
子句,即

public IEnumerable<Entities.BusinessDirectory.BDEntity> Search(string searchExpression)
{
    var db = new ApplicationDbContext();
    return db.BDEntities
             .Where(x => searchExpression.Split(' ').Any(y => x.Value.Contains(y)));
}
但是,我收到以下错误:

错误6实例参数:无法从转换 “System.Linq.Expressions.Expression>”到 “System.Linq.ParallelQuery”Extensions.cs


简单的答案是,您可以只向查询
Where
子句添加一个谓词,请记住
Where
谓词的定义是它返回
bool
。最终,您的表达式必须是
布尔表达式
才能添加到
Where
子句中

Expression<Func<BDEntity, bool>> predicate = (BDEntity entity) => entity.Field == "TEST";
var query = context.BDEntities;

if (predicate != null)
    query = query.Where(predicate);

// expand to get the results.
var results = query.ToList();
以下断言将通过:

var expression = Predicate.BuildEqualPredicate<MyDbEntity>(_ => _.DatabaseField, "TEST");
expression.Compile()
    .Invoke(new MyDbEntity { DatabaseField = "TEST" })
    .Should().BeTrue();
expression.Compile()
    .Invoke(new MyDbEntity { DatabaseField = "ANOTHERVALUE"})
    .Should().BeFalse();
您可以像这样动态创建一个谓词,在本例中,它创建一个谓词,用于检查字符串
是否以某个特定值开始,
或是否为null

private Expression<Func<T, bool>> BuildPredicate(
    string term,
    Expression<Func<T, string>> memberAccessor)
{
    var startsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
    var isNull = typeof(string).GetMethod("IsNullOrEmpty", new[] { typeof(string) });
    var toString = Expression.Convert(Expression.Constant(term), typeof(string));
    Expression expression = Expression.Call(
        memberAccessor.Body,
        startsWith,
        new Expression[] { toString });
    expression = Expression.Or(expression, Expression.Call(
        isNull,
        toString));
    var predicate = Expression.Lambda<Func<T, bool>>(
        expression,
        memberAccessor.Parameters);
    return predicate;
}
私有表达式构建谓词(
字符串项,
表达式成员(访问器)
{
var startsWith=typeof(string).GetMethod(“startsWith”,new[]{typeof(string)});
var isNull=typeof(string).GetMethod(“IsNullOrEmpty”,new[]{typeof(string)});
var-toString=Expression.Convert(Expression.Constant(term),typeof(string));
Expression=Expression.Call(
memberAccessor.Body,
开始,
新表达式[]{toString});
expression=expression.Or(expression,expression.Call(
isNull,
toString);
var谓词=表达式.Lambda(
表情,
成员访问器参数);
返回谓词;
}
这将为您提供一个计算结果如下的表达式:

Expression<Func<BDEntity, bool>> expression = _ => 
   string.IsNullOrEmpty(term)
   || _.DBEntityField.StartsWith(term)
Expression=\u=>
string.IsNullOrEmpty(术语)
||_u.DBEntityField.StartsWith(术语)
此表达式有几个优点:

  • 它可以转换为合适的
    SQL
  • term
    null
    empty
  • StartsWith
    确保可以使用适当的索引

可以使用
query=query类似地将
表达式添加到查询中。其中(表达式)
,将
StartsWith
替换为
Contains
将搜索字符串中的任何匹配项,但您将放弃任何SQL索引优化,所以这是禁忌。

谓词
代表什么?请添加一个如何使用此方法的示例。您没有处理数据库上下文
db
。但你肯定是在你真正的应用程序中这么做的,对吗?是吗?你好,吉姆,我想你给我指出了正确的方向。但是,我仍然无法通过使用定义属性==searchExpression的谓词(“表达式谓词”)来建立继承的DbContext类的扩展方法。如何通过组合谓词和字符串来构建表达式?我现在正在更新答案。答案很好。我还要补充一点,您需要小心Linq表达式中的捕获。例如,
searchExpression.Split(“”)
将捕获
seachExpression
,然后调用
string.Split
,这是不可EF调用的。Jim-以您的例子:可以使用t代替类BDEntity,即
表达式谓词=(t entity)=>{field searchExpression而{field}是函数参数中的谓词表达式?您可以为{T}使用任何占位符。泛型类型需要解析为特定的类或接口,才能具有特定的属性。给定:
(T entity)=>entity.SomeField==searchExpression
,T需要是具有名为
SomeField
的属性的接口或类。在这种情况下,我通常要做的是确保具有属性
SomeField
的每个实体框架实体都继承一个特定接口<例如,代码>ISearchable
。所有
ISearchable
实体都将具有属性
SomeField
。然后键入{T}
,其中T:ISearchable
var predicate = PredicateExtensions.BuildEqualPredicate<MyDbEntity>(
    _ => _.DatabaseField,
    "TEST");
var results = context.DbEntity.Where(predicate).ToList();
Expression<Func<T, string>> memberAccessor = _ => _.DBEntityField;
private Expression<Func<T, bool>> BuildPredicate(
    string term,
    Expression<Func<T, string>> memberAccessor)
{
    var startsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
    var isNull = typeof(string).GetMethod("IsNullOrEmpty", new[] { typeof(string) });
    var toString = Expression.Convert(Expression.Constant(term), typeof(string));
    Expression expression = Expression.Call(
        memberAccessor.Body,
        startsWith,
        new Expression[] { toString });
    expression = Expression.Or(expression, Expression.Call(
        isNull,
        toString));
    var predicate = Expression.Lambda<Func<T, bool>>(
        expression,
        memberAccessor.Parameters);
    return predicate;
}
Expression<Func<BDEntity, bool>> expression = _ => 
   string.IsNullOrEmpty(term)
   || _.DBEntityField.StartsWith(term)