Не удается десериализовать из ObjectId в String в запросе коллекции MongoDb - PullRequest
1 голос
/ 29 марта 2019

Всякий раз, когда я пытаюсь получить список идентификаторов из коллекции:

var messages = db.GetCollection<MessageExchange>(collectionName);
var ids = messages
   .AsQueryable()
   .Where(_=> true)
   .Select(x => x.Id)
   .ToList();

Я получаю ошибку приведения:

System.FormatException HResult = 0x80131537 Сообщение = невозможно десериализовать 'String' из BsonType 'ObjectId'. Source = StackTrace:

Я не могу изменить определение класса, потому что он реализован в пакете, который я не могу изменить. Поэтому решение вопроса:

[BsonRepresentation(BsonType.ObjectId)] 

на нем невозможно . На основании это .

Можно ли привести это в запросе Linq?

Ответы [ 3 ]

3 голосов
/ 29 марта 2019

Нет, потому что db.GetCollection<MessageExchange> определяет коллекцию как строго типизированные объекты, которые драйвер будет обрабатывать в сочетании с любой дальнейшей логикой, выполняемой (с использованием linq или иным способом).

Ваши лучшие варианты::

  1. Определите класс, совместимый с вашей коллекцией Mongo, в своем собственном коде, а затем используйте этот класс для десериализации ваших результатов db.GetCollection<MyCustomMessageExchange>, которые затем можно использовать в приведенном выше запросе linq длявыберите только идентификаторы.

  2. Просто используйте значение по умолчанию BsonDocument, чтобы определить свою коллекцию, и используйте проекцию: db.GetCollection<BsonDocument>.Find(new BsonDocument()).Project("{_id: 1}").ToList()

2 голосов
/ 29 марта 2019

Вы ни в коем случае не обязаны использовать whats в пакете - если вы знаете, каково определение класса, я бы посоветовал добавить свой собственный MessageExchange в свой проект и использовать его для запроса коллекции с помощью драйвера.

Это также позволяет вам получать только те поля, которые вам нужны (используя атрибут [BsonIgnoreExtraElements] в вашем новом классе), а не то, что навязывает вам автор пакета.

Если используется тип MessageExchange абсолютно необходимо для потока вашей программы и структуры. Я бы предложил использовать что-то вроде AutoMapper для возврата к исходному типу из вашего собственного.

1 голос
/ 29 марта 2019

В структуре ObjectId реализован метод ToString , позволяющий преобразовать объект в его строковое представление.

Так что я думаю, что вы можете сделать:

var messages = db.GetCollection<MessageExchange>(collectionName);
var ids = messages
   .AsQueryable()
   .Where(_=> true)
   .Select(x => x.Id.ToString())
   .ToList();
...