How to deserialize a BsonDocument object back to class
There are three ways actually:
1.Specify type you want to load directly in FindAs<>
var docs = _collection.FindAs<MyType>(_document);
2.Deserialize document via BsonSerializer
:
BsonSerializer.Deserialize<MyType>(doc);
3.Map bson document manually to your class:
var myClass = new Mytype();
myClass.Name = bsonDoc["name"].AsString;
For most cases you are okay with first approach. But sometimes, when your documents is unstructured, you may need third approach.
For big applications and which has some structured data, it's recommended to use your custom model while creating and getting the data instead of using BsonDocument.
Creating a model is an important step for deserialization.
Helpful annotations to remember while creating your model:
- add
id
property in model. Try to use[BsonId]
attribute for good practice: - Create a property with annotation as
[BsonExtraElements]
this will be used to hold any extra elements found during deserialization. - you can use
[BsonElement]
to specify the elementName. -
[BsonIgnoreIfDefault]
- Initializes a new instance of the BsonIgnoreIfDefaultAttribute class
Sample Model structure, where I tried to cover maximum cases. I have created a base class for _id property just for better architecture, but you can use directly in MyModel
class as well.
public abstract class BaseEntity
{
// if you'd like to delegate another property to map onto _id then you can decorate it with the BsonIdAttribute, like this
[BsonId]
public string id { get; set; }
}
public class MyModel: BaseEntity
{
[BsonElement("PopulationAsOn")]
public DateTime? PopulationAsOn { get; set; }
[BsonRepresentation(BsonType.String)]
[BsonElement("CountryId")]
public int CountryId { get; set; }
[Required(AllowEmptyStrings = false)]
[StringLength(5)]
[BsonIgnoreIfDefault]
public virtual string CountryCode { get; set; }
[BsonIgnoreIfDefault]
public IList<States> States { get; set; }
[BsonExtraElements]
public BsonDocument ExtraElements { get; set; }
}
Now to Deserialise, directly use your model while calling FindAsync
like this:
cursor = await _collection.FindAsync(filter,
new FindOptions<MyModel, MyModel>()
{ BatchSize = 1000, Sort = sort }, ct);