C# 如何动态创建表达式<;Func<&燃气轮机&燃气轮机;对于count和group by子句
我需要为Cosmos DB中的以下查询创建动态lambda表达式谓词C# 如何动态创建表达式<;Func<&燃气轮机&燃气轮机;对于count和group by子句,c#,azure-cosmosdb,predicate,generic-lambda,dynamic-expression,C#,Azure Cosmosdb,Predicate,Generic Lambda,Dynamic Expression,我需要为Cosmos DB中的以下查询创建动态lambda表达式谓词 *select City, COUNT(City) as CityCount FROM Cities where status="Active" group by City* 前面我已经创建了这样的相等操作 var parameter = Expression.Parameter(typeof(T), "t"); MemberExpression expBody = Expressi
*select City, COUNT(City) as CityCount FROM Cities where status="Active"
group by City*
前面我已经创建了这样的相等操作
var parameter = Expression.Parameter(typeof(T), "t");
MemberExpression expBody = Expression.Property(parameter, columnName);
但是对于获取
Count
和groupby
子句,如何做到这一点。我对CosmoDB不熟悉,但LINQ不是更容易做到这一点吗
IQueryable查询
=cityContainer.GetItemLinqQueryable()
.Where(城市=>城市状态==“活动”)
.GroupBy(城市=>城市);
使用FeedIterator iterator=query.ToFeedIterator();
int cityCount=0;
for(;iterator.HasMoreResults;cityCount++)
{
City=等待setIterator.ReadNextAsync();
//做事
}
编辑:
我在评论中的答案示例->
struct City
{
public string Name { get; set; }
public int Population { get; set; }
}
IQueryable<City> cities = default;
Func<City, bool> HasNastyName = c => c.Name.Length > 25;
Func<City, bool> IsMassive = c => c.Population > 500;
var nastyNameCities = cities.Where(HasNastyName);
var massiveCities = cities.Where(IsMassive);
struct城市
{
公共字符串名称{get;set;}
公共整数填充{get;set;}
}
IQueryable cities=默认值;
Func HasNastyName=c=>c.Name.Length>25;
Func IsMassive=c=>c.总体>500;
var nastyNameCities=cities.Where(HasNastyName);
var massiveCities=城市,其中(IsMassive);
考虑到一般地构建这些谓词的附加选项,您可以使用LINQ非常动态地构建谓词。
我可能不知道你想做什么,但我看不到这里使用表达式树有什么好处
CosmoDB的IQueryProvider已经在为您翻译所有查询,因此,除非我不知道什么,否则您正在编写不必要的、可能优化程度较低的实现,方法是将表达式映射到查询本身。我相信您可以使用dynamic Linq实现这一点:
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Linq.Dynamic.Core;
名称空间控制台App7
{
班级计划
{
静态void Main(字符串[]参数)
{
IQueryable testData=新的EnumerableQuery(新列表());
var query=testData
.其中(o=>o.Active)
.GroupBy(“城市”)
。选择(“新建(键为城市,计数()为城市计数)”;
控制台。WriteLine(“你好,世界!”);
}
}
公共级MyOb
{
公共字符串City{get;set;}
公共bool活动{get;set;}
}
}
动态Linq的文档提供了这个示例
var result=context.Posts.GroupBy(“BlogId”)。选择(“new(Key,Count()AS Count)”;
Count
和GroupBy
是方法。因此,首先需要使用反射获取相应的MethodInfo
s(注意从Queryable
类中获取方法,而不是从Enumerable
和正确的重载中获取方法!)
然后使用expression.call(null,methodInfo,queryable)
创建一个方法调用表达式。(第一个参数应该是null
,因为这两个方法都是静态的。)这里,queryable
是您已经建立的IQueryable
,您要分别调用Count
或GroupBy
。对于GroupBy
,您还需要添加一个额外的参数,即用于投影City
属性的lambda表达式-我假设您知道如何构建它
更新 但如果我正确理解您的动机,您实际上是在尝试根据从库中获得的基本
IQueryable
动态构建一个包含where子句、select、groupby和/或counts的IQueryable
,对吗
在这种情况下,不应将
Count
和GroupBy
表示为表达式。相反,您应该在您的基础上动态调用真正的方法Where
、Select
、Count
和GroupBy
(以获得另一个IQueryable
),但动态地为这些方法的参数构建lambda表达式。最后,您将拥有一个IQueryable
,Cosmos DB LINQ提供商可以对其进行评估。您是否使用EntityFramework?如果是这样的话,可能值得检查dynamic linq@Jason。我不确定EF Core CosmosDB提供程序是否支持dynamic linq。对于Count
,这可能会有所帮助:我必须使用表达式生成器,就像我们在创建泛型谓词时使用的代码一样。你能提供一个如何使用这些谓词的示例吗?在where子句中有一个子查询的想法吗?我们如何使用Expression builder来实现这一点,就像我们在项目中使用它来创建泛型谓词一样。?我不确定您到底在做什么,但IQueryable的.where()方法已经采用了泛型谓词,所以如果你用这种方法而不是建立一个表达式树,我假设你已经得到了你想要的?是的,你说得对。我也想这样做。我会尝试你的建议,并让你知道。我尝试了,但没有工作,你能给我一个这样的例子。