在CosmosDb上的Linq.Where()中使用Linq.Any()
我试图在.Where()
子句中嵌套.Any .Where()
来查询本地CosmosDb模拟器。
代码如下所示; 其中allowedStundentIds是变量( List
), a
是CosmosDb中的Document
.Where(a => permittedStudentIds.Any(sId => a.Students.Any(s => s.Id == sId)));
当我执行查询时,我收到错误:
方法’Any’不受支持。 ActivityId:800000a8-0002-d600-b63f-84710c7967bb,documentdb-dotnet-sdk / 1.22.0主机/ 64位MicrosoftWindowsNT / 10.0.16299.0
我尝试了多种变体来获得等效表达,但无济于事。 唯一有效的是使用.Contains()
并对学生索引进行硬编码; 这是不可行的,因为可能不知道学生人数。
.Where(a => permittedStudentIds.Contains(a.Students[0].Id));
我确实理解在CosmosDb的Sql API上尚不支持某些lambda扩展,但有没有解决方法呢?
在尝试了各种lambda表达式的多种组合之后,这对我来说是有用的。
我在我的DocumentModel
类中添加了一个StudentIds
属性; 冗余但仅用于过滤。
之后,我使用.Contains()
对查询进行OR-ed
,如下所示:
Expression> query = a => a.StudentIds.Contains(permittedStudentIds[0]); foreach (var id in permittedStudentIds.Skip(1)) { query = query.Or(a => a.StudentIds.Contains(id)); }
然后使用如下查询:
.Where(query);
对于query.Or()
部分,我使用了以下类:
// See: https://blogs.msdn.microsoft.com/meek/2008/05/02/linq-to-entities-combining-predicates/ public static class ExpressionExtensions { public static Expression Compose (this Expression first, Expression second, Func merge) { // build parameter map (from parameters of second to parameters of first) var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => ps, p => pf); // replace parameters in the second lambda expression with parameters from the first var secondBody = ParameterVistor.ReplaceParameters(map, second.Body); // apply composition of lambda expression bodies to parameters from the first expression return Expression.Lambda (merge(first.Body, secondBody), first.Parameters); } public static Expression> And (this Expression> first, Expression> second) { return first.Compose(second, Expression.AndAlso); } public static Expression> Or (this Expression> first, Expression> second) { return first.Compose(second, Expression.OrElse); } } public class ParameterVistor : ExpressionVisitor { private readonly Dictionary map; public ParameterVistor(Dictionary map) { this.map = map ?? new Dictionary(); } public static Expression ReplaceParameters(Dictionary map, Expression exp) { return new ParameterVistor(map).Visit(exp); } protected override Expression VisitParameter(ParameterExpression p) { ParameterExpression replacement; if (map.TryGetValue(p, out replacement)) { p = replacement; } return base.VisitParameter(p); } }
因此,您有一系列allowedStudentIds和一个包含学生序列的文档。 每个学生都有一个Id。
您想知道是否有任何allowedStudentsId也是您的文档学生中一个(或多个)的ID。
换句话说,如果allowedStudentIds的值为1,2,则您想知道Document.Students中是否有ID为1或2的学生。
为什么不提取所有学生的ID,将它们与您的allowedStudentIds相交并查看结果是否为空?
var studentIds = Document.Students.Select(student => student.Id); var intersection = studentIds.Intersect(permittedStudentIds); var result = intersection.Any(); // TODO: make one statement.
如果两个序列都是AsQueryable,则它可以工作,但如果您的Document.Students是IQueryable并且您的allowedStudentIds是IEnumerable,它也可以工作。 我最好的猜测是,这将成为一个SQL包含。 请参见Queryable.Intersect
上述就是C#学习教程:在CosmosDb上的Linq.Where()中使用Linq.Any()分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/949218.html