如何在C#中使用Func/表达式创建查询对象?
我想为使用ElasticSearch的项目创建一个可重用的查询对象。我已经在使用LongLe提供的类似工具来查询使用实体框架的数据库 我真的不知道该怎么做——我不知道如何将lambda表达式的各个部分“链接”在一起。我尝试过使用Expression/Func,但这对我来说是一个新领域,我并不完全理解。我觉得自己就像是在黑暗中刺伤 由于我甚至不知道如何准确地表达我的问题,下面是一个我目前正在做的事情、我正在尝试做的事情以及我迄今为止的进展的例子: 我目前必须做的事情:如何在C#中使用Func/表达式创建查询对象?,c#,expression,nest,func,C#,Expression,Nest,Func,我想为使用ElasticSearch的项目创建一个可重用的查询对象。我已经在使用LongLe提供的类似工具来查询使用实体框架的数据库 我真的不知道该怎么做——我不知道如何将lambda表达式的各个部分“链接”在一起。我尝试过使用Expression/Func,但这对我来说是一个新领域,我并不完全理解。我觉得自己就像是在黑暗中刺伤 由于我甚至不知道如何准确地表达我的问题,下面是一个我目前正在做的事情、我正在尝试做的事情以及我迄今为止的进展的例子: 我目前必须做的事情: ISearchRes
ISearchResponse<DemoIndexModel> result = client.Search<DemoIndexModel>(s => s.Query(
q => q.Term(t => t.FirstName, firstName)
&& q.Term(t => t.LastName, lastName)));
var query = new DemoIndexQuery();
query = query.ByFirstName(firstName);
query = query.ByLastName(lastName);
result = client.Search<DemoIndexModel>(s => s.Query(query.Compile()));
public abstract class ElasticQueryObject<T> where T : class
{
private Func<QueryDescriptor<T>, QueryContainer> _query;
// tried using Expression, still completely lost
private Expression<Func<QueryDescriptor<T>, QueryContainer>> _expression;
public Func<QueryDescriptor<T>, QueryContainer> Compile()
{
return _query;
}
public Func<QueryDescriptor<T>, QueryContainer> And(Func<QueryDescriptor<T>, QueryContainer> query)
{
if (_query == null)
{
_query = query;
}
else
{
// how do I chain the query??? I only can figure out how to set it.
}
return null;
}
}
public class DemoIndexQuery : ElasticQueryObject<DemoIndexModel>
{
public DemoIndexQuery ByFirstName(string firstName)
{
And(p => p.Term(term => term.FirstName, firstName));
return this;
}
public DemoIndexQuery ByLastName(string lastName)
{
And(p => p.Term(term => term.LastName, lastName));
return this;
}
}
ISearchResponse结果=client.Search(s=>s.Query(
q=>q.Term(t=>t.FirstName,FirstName)
&&术语(t=>t.LastName,LastName));
我想做什么:
ISearchResponse<DemoIndexModel> result = client.Search<DemoIndexModel>(s => s.Query(
q => q.Term(t => t.FirstName, firstName)
&& q.Term(t => t.LastName, lastName)));
var query = new DemoIndexQuery();
query = query.ByFirstName(firstName);
query = query.ByLastName(lastName);
result = client.Search<DemoIndexModel>(s => s.Query(query.Compile()));
public abstract class ElasticQueryObject<T> where T : class
{
private Func<QueryDescriptor<T>, QueryContainer> _query;
// tried using Expression, still completely lost
private Expression<Func<QueryDescriptor<T>, QueryContainer>> _expression;
public Func<QueryDescriptor<T>, QueryContainer> Compile()
{
return _query;
}
public Func<QueryDescriptor<T>, QueryContainer> And(Func<QueryDescriptor<T>, QueryContainer> query)
{
if (_query == null)
{
_query = query;
}
else
{
// how do I chain the query??? I only can figure out how to set it.
}
return null;
}
}
public class DemoIndexQuery : ElasticQueryObject<DemoIndexModel>
{
public DemoIndexQuery ByFirstName(string firstName)
{
And(p => p.Term(term => term.FirstName, firstName));
return this;
}
public DemoIndexQuery ByLastName(string lastName)
{
And(p => p.Term(term => term.LastName, lastName));
return this;
}
}
var query=new DemoIndexQuery();
query=query.ByFirstName(firstName);
query=query.ByLastName(lastName);
结果=client.Search(s=>s.Query(Query.Compile());
到目前为止的代码:
ISearchResponse<DemoIndexModel> result = client.Search<DemoIndexModel>(s => s.Query(
q => q.Term(t => t.FirstName, firstName)
&& q.Term(t => t.LastName, lastName)));
var query = new DemoIndexQuery();
query = query.ByFirstName(firstName);
query = query.ByLastName(lastName);
result = client.Search<DemoIndexModel>(s => s.Query(query.Compile()));
public abstract class ElasticQueryObject<T> where T : class
{
private Func<QueryDescriptor<T>, QueryContainer> _query;
// tried using Expression, still completely lost
private Expression<Func<QueryDescriptor<T>, QueryContainer>> _expression;
public Func<QueryDescriptor<T>, QueryContainer> Compile()
{
return _query;
}
public Func<QueryDescriptor<T>, QueryContainer> And(Func<QueryDescriptor<T>, QueryContainer> query)
{
if (_query == null)
{
_query = query;
}
else
{
// how do I chain the query??? I only can figure out how to set it.
}
return null;
}
}
public class DemoIndexQuery : ElasticQueryObject<DemoIndexModel>
{
public DemoIndexQuery ByFirstName(string firstName)
{
And(p => p.Term(term => term.FirstName, firstName));
return this;
}
public DemoIndexQuery ByLastName(string lastName)
{
And(p => p.Term(term => term.LastName, lastName));
return this;
}
}
公共抽象类ElasticQueryObject,其中T:class
{
私有函数查询;
//尝试使用表达式,但仍然完全失败
私人表达(private Expression);
公共函数编译()
{
返回查询;
}
公共函数和(函数查询)
{
if(_query==null)
{
_查询=查询;
}
其他的
{
//如何链接查询???我只知道如何设置查询。
}
返回null;
}
}
公共类DemoIndexQuery:ElasticQueryObject
{
public DemoIndexQuery ByFirstName(字符串名)
{
和(p=>p.Term(Term=>Term.FirstName,FirstName));
归还这个;
}
公共DemoIndexQuery ByLastName(字符串lastName)
{
和(p=>p.Term(Term=>Term.LastName,LastName));
归还这个;
}
}
您正在违反LINQ合同。查询应该是不可变的——所有对查询进行操作的方法都应该返回一个新查询,而不是修改旧查询。由于查询的构建方式,它本质上是可组合的,因此
public DemoIndexQuery ByFirstName(string firstName)
{
And(p => p.Term(term => term.FirstName, firstName));
return this;
}
您只需使用以下功能:
public DemoIndexQuery ByFirstName(string firstName)
{
return Where(p => p.Term(term => term.FirstName, firstName));
}
如果由于某种原因这是不可能的,那么在向前传递表达式树之前,您需要自己构建表达式树。最简单的方法如下:
Expression<...> oldQuery = ...;
var newCondition = (Expression<...>)(p => p.Term(...));
return Expression.And(oldQuery, newCondition);
表达式oldQuery=。。。;
var newCondition=(表达式)(p=>p.Term(…);
返回表达式和(oldQuery、newCondition);
如果您的查询提供程序不支持这一点,您需要做更多的工作-您可以单独构建整个where谓词,然后确保修复lambdas和lambda参数。那么,问题出在哪里?除了不返回修改后的查询之外,我的意思是,查询对象不是不起作用的部分,我试图理解如何链接表达式的各个部分。我没有
Where()
选项。如何准确地为Func构建表达式树?@DoctorOreoexpression
是一个lambda表达式-您可以使用expression.lambda
创建它。棘手的部分是正确映射lambda参数-您需要在声明中使用相同的ParameterExpression
,以后再使用。