Anthony Bias
Anthony Bias

Reputation: 646

MongoDB .NET Driver Mapping values as null

I'm using MongoDB Driver to try and map BsonDocument to a model. When I try to read models from a collection, string values are null, DateTimes are the minimum value, and enums are their default value. Here is a document I'd like to read from a collection:

enter image description here

This is the class I'd like to map it to:

public class PhotoModel
{
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }
    public string Name { get; set; }
    [BsonSerializer(typeof(PhotoCategorySerializer))]
    public PhotoCategory Category { get; set; }
    public string Description { get; set; }
    public string UserID { get; set; }
    public DateTime Created { get; set; }
}

Here is where I define the mapping:

BsonClassMap.RegisterClassMap<PhotoModel>(cm =>
        {
            cm.MapMember(c => c.Id);
            cm.MapMember(c => c.Name);
            cm.MapMember(c => c.Description);
            cm.MapMember(c => c.Category);
            cm.MapMember(c => c.UserID);
            cm.MapMember(c => c.Created);
        });

I use MapMember instead of AutoMap because I don't want file to be a part of my model. This is the code where I try to read from the collection:

public class PhotoRepository : IPhotoRepository
{
    private readonly IMongoCollection<PhotoModel> photos;

    public PhotoRepository(IMongoClient mongoClient)
    {
        photos = mongoClient.GetDatabase("photo-share").GetCollection<PhotoModel>("photos");
    }

    public IEnumerable<PhotoModel> GetAllPhotos() => photos.Find(new BsonDocument()).ToList();
}

This is what I see when I debug photos.Find(new BsonDocument()).ToList(): enter image description here

Why is the class not mapped properly?

Also, a related question: where should I perform the mappings? The docs said to register class maps before initializing a MongoDB connection, so I do it in Program.cs before the host is built and run. Is that a good place for it?

Upvotes: 1

Views: 1353

Answers (1)

Dĵ ΝιΓΞΗΛψΚ
Dĵ ΝιΓΞΗΛψΚ

Reputation: 5679

do it like this. you don't even need to specify mapping. mongo driver takes care of that. your main problem is the mismatched casing of db field names and class property names.

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace StackOverflow
{
    [BsonIgnoreExtraElements]
    public class PhotoModel
    {
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id { get; set; }

        [BsonElement("name")]
        public string Name { get; set; }

        [BsonElement("category"), BsonSerializer(typeof(PhotoCategorySerializer))]
        public PhotoCategory Category { get; set; }

        [BsonElement("description")]
        public string Description { get; set; }

        [BsonElement("userID")]
        public string UserID { get; set; }

        [BsonElement("created")]
        public DateTime Created { get; set; }
    }

    internal static class Program
    {
        private static readonly IMongoClient client = 
            new MongoClient("mongodb://localhost");

        private static readonly IMongoCollection<PhotoModel> photoCollection =
            client.GetDatabase("photo-share").GetCollection<PhotoModel>("photos");

        private static async Task Main()
        {
            IEnumerable<PhotoModel> photos = await photoCollection.Find(_ => true).ToListAsync();
        }
    }
}

you could even eliminate the need for the attribute decorations by registering a convension pack like so:

ConventionRegistry.Register(
    "MyConvensions",
    new ConventionPack
    {
        new IgnoreExtraElementsConvention(true),
        new CamelCaseElementNameConvention()
    },
    _ => true);

Upvotes: 1

Related Questions