Так что в этом случае Я думаю, что вы хотите IQueryable
вместо IEnumerable
.Самый простой способ запомнить это то, что IEnumerable
загружает все данные в память, а затем выполняет остальную часть вашего запроса LINQ, в то время как IQueryable
пытается запустить ваши фильтры на источнике, если он может затем загрузить полученные данные в память.Вам необходимо использовать ORM, который поддерживает IQueriable
, такой как LINQ to SQL или Entity Framework.В случае CosmosDB SDK построен поверх LINQ to SQL.
Используя IEnumerable
, вы загружаете все данные из Cosmos в память, а затем применяете ваши фильтры инумерацией страниц.Это нормально, пока у вас есть только несколько записей, но по мере роста вашего набора данных вы, вероятно, можете представить, как это может стать серьезной проблемой.Обычно вы хотите выполнить как можно больше работы с базой данных и вернуть только минимальное количество результатов.Это намного перевесит любые соображения производительности при использовании отражения для построения ваших предикатов.
Одна из лучших частей IQueryable
заключается в том, что он наследуется от IEnumerable
, поэтому все, что работает с IEnumerable
, будет работатьс IQueriable
.Все, что вам нужно сделать, это избавиться от AsEnumerable()
.
Важно отметить, что не все операторы LINQ поддерживаются автоматически, и как только система нажмет один, она не сможетперевести это выполняет то, что он имеет до сих пор и делает все остальное в памяти.В документации есть список доступных операторов для CosmosDB.
Для вашего запроса будет большой, в то время как ваше предложение Where()
поддерживается, Skip()
и Take()
в настоящее время нет.Это означает, что каждый раз, когда этот метод выполняется, все результаты будут возвращаться из CosmosDB, а затем будет оцениваться нумерация страниц.
В SDK есть несколько способов справиться с нумерацией страниц.Поддерживаемый в настоящее время способ - установить MaxItemCount
внутри вашего FeedOptions
на размер вашей страницы.Вместо функции Skip()
текущая система использует токены продолжения.Для доступа к токену вы можете использовать AsDocumentQuery()
.Поскольку вам нужно переходить от каждой страницы к следующей, кэширование токенов может быть очень полезным - прыгать вокруг очень сложно.
Второй вариант - использовать v3 .Net SDK.Это в настоящее время в предварительном просмотре, но доступно на Nuget .Несколько месяцев назад skip / take было включено .В этом случае все до тех пор, пока вы не вызовете ToList()
, должно быть переведено в SQL и оценено в CosmosDB.