Search code examples
c#.netmongodbmongodb-.net-driver

Why am I getting Error retrieving mongo document in .net?


I have inserted a document into a collection in MongoDB

public class Product :BaseDocument, IProduct
    {
        public Guid ProductId { get; set; }
        public string ProductName { get; set; }
        public Guid AccountId { get; set; }
        public List<IProductDetail> ProductDetailList { get; set; } = new List<IProductDetail>();
    }

public class ProductDetail:IProductDetail
        {
            public Guid ProductDetailId { get; set; }
            public string ProductDetailCode { get; set; }
        }

When I try to retrieve this though, I get an error

public List<IProduct> GetProductsList(Guid accountId)
        {
            IEnumerable<IProduct> prodList = new List<Product>();
            IMongoCollection<Product> products = _database.GetCollection<Product>("Products");
            prodList = products.Find(m => m.AccountId == accountId).ToList();
            return prodList.ToList();
        }

The error is as follows

System.FormatException: 'An error occurred while deserializing the ProductDetailList property of class Entities.ProductDetail: Unknown discriminator value 'ProductDetail'.'

What am I doing wrong?


Solution

  • The reason why you're getting this error is that MongoDB .NET driver doesn't know how to resolve IProductDetail and it tries to instantiate ProductDetail class since there is a _t field representing that type stored in MongoDB.

    Usually you can use BsonKnownTypes in that kind of polymorphic scenario but it works only for classes and structs. So if you want to preserve some class hierarchy here then you need to introduce an abstract class and apply this attribute there.

    [BsonKnownTypes(typeof(ProductDetail))]
    public abstract class ProductDetailBase: IProductDetail
    {
    }
    
    public class ProductDetail : ProductDetailBase
    {
        public Guid ProductDetailId { get; set; }
        public string ProductDetailCode { get; set; }
    }
    

    and then you can use:

    public List<ProductDetailBase> ProductDetailList { get; set; } = new List<ProductDetailBase>();
    

    In such case you can have a class hierarchy and MongoDB .NET driver will deserialize your BSON document into appropriate child class in runtime.