IQueryable возвращает пустой результат после выполнения запроса LINQ

#c# #.net #linq #azure-cosmosdb #iqueryable

#c# #.net #linq #azure-cosmosdb #iqueryable

Вопрос:

Я использую Microsoft.Azure.Документы.Интерфейс IDocumentClient для доступа к документам CosmosDB с использованием метода CreateDocumentQuery.

Когда я запускаю код без включения каких-либо запросов linq, я без проблем получаю все свои документы:

 client.CreateDocumentQuery<MyDatabaseClass>(CollectionUri, options)
      .ToList()
  

Я хочу получить идентификатор документов, поэтому я пробую следующий код:

 client.CreateDocumentQuery<MyDatabaseClass>(CollectionUri, options)
      .Select(doc => doc.Id)
      .ToList()
  

И это возвращает 0 результатов.

Если я переключу его и перечислю IQueryable перед выполнением запроса, он работает нормально, но, насколько я понимаю этот материал (хотя есть большая вероятность, что я этого не делаю), это менее эффективно.

 client.CreateDocumentQuery<MyDatabaseClass>(CollectionUri, options)
      .ToList()
      .Select(doc => doc.Id)
  

Кто-нибудь знает, что я делаю неправильно с запрашиваемым, чтобы это произошло? (Обратите внимание, приведенное выше является упрощенной версией того, чего я на самом деле пытаюсь достичь, но проблема все еще возникает даже на этом уровне).

Схема элемента базы данных:

 {
  "type": "",
  "view": {
    "date": "",
    "paths": {}
  },
  "id": "",
  "viewId": ""
  "version": "",
  "_rid": "",
  "_self": "",
  "_etag": "",
  "_attachments": "",
  "_ts": ""
}
  

Класс:

 public string Id{ get; private set; }

public string ViewId { get; private set; }

public string Version { get; private set; }

public abstract string Type { get; }
  

Комментарии:

1. Я не знаю эту базу данных, но запросы linqs не могут преобразовать все запросы на язык базы данных. В SQL Server обычно отображаются предупреждения типа «преобразовать запрос не удалось». И код генерирует несколько запросов SQL для выполнения одного запроса Linq (вероятно, неэффективно). Итак, я полагаю, что эта проблема возникает в вашем случае. Он не может фильтровать на языке вашей базы данных. Но если вы используете ToList (), в котором все данные загружаются в память, возможна фильтрация. Но неэффективно. Попробуйте прочитать документацию db, чтобы убедиться в проблеме.

2. Очевидно, что существует проблема с оценкой запроса на стороне сервера. Можете ли вы предоставить свой реальный запрос и некоторые примеры объектов базы данных, которые связаны с ним?

3. @Paulo, я использую CosmosDB amp; IDocumentClient, которые, как описано здесь, должны иметь возможность использовать LINQ. Однако есть параметры SQL, поэтому я попробую. learn.microsoft.com/en-us/dotnet/api /…

4. @Plusce, простая инструкция select выше — это реальный запрос, который не будет работать. Элементы базы данных выглядят следующим образом: { "type": "", "view": { "date": "", "paths": { } }, "id": "", "version": "", "_rid": "", "_self": "", "_etag": "", "_attachments": "", "_ts": }

5. Пожалуйста, отредактируйте свой вопрос и добавьте элемент базы данных, правильно отформатированный к вашему вопросу. Не могли бы вы также указать нам, IQueryable<...> что возвращает CreateDocumentQuery<MyDatabaseClass>(…)?

Ответ №1:

Если вы специально не привязаны к LINQ для построения запросов, рассмотрите возможность использования QueryDefinition класса в .NET SDK для определения ваших запросов в синтаксисе SQL для запуска в Cosmos. В идеале любая фильтрация или формирование выполняются запросом, а не в коде для результата.

Смотрите этот пример для хорошей отправной точки. Только для выбора идентификатора:

 QueryDefinition query = new QueryDefinition("select c.id from c");

// Provide query to container.GetItemQueryIterator<MyDatabaseClass>()
  

Ответ №2:

Я смог обойти эту проблему, используя перегрузку CreateDocumentQuery, которая принимает SQL-запрос вместо использования LINQ.