Can't deserialize from ObjectId to String in a MongoDb collection query

1

Whenever I am trying to get a list of Ids from a collection:

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

I am getting a cast error:

System.FormatException HResult=0x80131537 Message=Cannot deserialize a 'String' from BsonType 'ObjectId'. Source= StackTrace:

I am not able to modify the definition of a class, because its implemented in a package I can't change. Therefore the solution of putting:

[BsonRepresentation(BsonType.ObjectId)] 

on it, is not possible. Based on this.

Is it possible to cast this in the Linq query?

c#
mongodb
casting
mongodb-.net-driver
asked on Stack Overflow Mar 29, 2019 by DanielV

3 Answers

3

No, because db.GetCollection<MessageExchange> defines the collection as strongly typed objects which the driver will process in combination with any further logic that is carried out (using linq or otherwise).

Your best options would be either:

  1. Define a class which is compatible with your Mongo Collection in your own code, then use that class to deserialise your results db.GetCollection<MyCustomMessageExchange> which you can then use with your linq query above to select just the ids.

  2. Just use the default BsonDocument to define your collection and use a projection: db.GetCollection<BsonDocument>.Find(new BsonDocument()).Project("{_id: 1}").ToList()

answered on Stack Overflow Mar 29, 2019 by Steve Land • edited Mar 29, 2019 by Steve Land
2

You are by no means bound to using whats in the package - if you know what the definition is of the class I would suggest rolling your own MessageExchange inside your project and using that to query the collection using the driver.

This allows you also to only get fields that you need(using [BsonIgnoreExtraElements] attribute on your new class) and not what the author of the package forces on you .

If using the type MessageExchange is absolutely necessary for your program flow and structure Id suggest using something like AutoMapper to cast back to the original type from your own one.

answered on Stack Overflow Mar 29, 2019 by cl0ud • edited Mar 29, 2019 by cl0ud
1

The ObjectId structure implements a ToString method, allowing you to convert the object into its string representation.

So I think you can do:

var messages = db.GetCollection<MessageExchange>(collectionName);
var ids = messages
   .AsQueryable()
   .Where(_=> true)
   .Select(x => x.Id.ToString())
   .ToList();
answered on Stack Overflow Mar 29, 2019 by Kunal Mukherjee

User contributions licensed under CC BY-SA 3.0