3

I have objects of different classes and would like to store them in a single collection in MongoDB.

I'm using asp.net core 2.2 with MongoDB.Driver 2.8.0 and MongoDB 4.0.5. I've done some attempts.

The idea: I can store all below objects in a single collection. Currently I can save them but I'm not able to read them -> getting "FormatException: Element '_id' does not match any field or property of class Mongo2.Models.MongoEntity." but only after re-running application. On empty database I can save object and retrieve them. When I close the app and don't drop the db then getting exception on collection.Find(book => true).ToList(); }

I guess I'm missing some steps or my approach is not valid - couldn't find any workable examples over the internet.

Any help will be much appreciated. Either by sharing links to working solutions / examples or here.

Model:

public class MongoEntity
{
}

[BsonIgnoreExtraElements]
public class BookLibrary : MongoEntity
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string BookLibraryId { get; set; }
    public List<Book> Library { get; set; }
}

[BsonIgnoreExtraElements]
public class Book : MongoEntity
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string BookId { get; set; }

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

    [BsonElement("Price")]
    public decimal Price { get; set; }

    [BsonElement("Category")]
    public Category Category { get; set; }

    [BsonElement("Author")]
    public Author Author { get; set; }

    [BsonElement("Date")]
    public DateTime Added { get; set; }
}

[BsonIgnoreExtraElements]
public class Author : MongoEntity
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string AuthorId { get; set; }
    [BsonElement("Author name")]
    public string Name { get; set; }
    [BsonElement("Author last name")]
    public string LastName { get; set; }
}

[BsonIgnoreExtraElements]
public class Category : MongoEntity
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string CategoryId { get; set; }
    [BsonElement("Category name")]
    public string CategoryName { get; set; }
}

Data context:

public class BookContext
{
    private readonly IMongoDatabase _database;
    private readonly IMongoClient _client;

    public BookContext(IConfiguration configuration)
    {
        _client = new MongoClient(configuration.GetSection(nameof(MongoDbSettings)).Get<MongoDbSettings>().ConnectionString);
        _database = _client.GetDatabase(configuration.GetSection(nameof(MongoDbSettings)).Get<MongoDbSettings>().DatabaseName);

    }

    public List<MongoEntity> Get()
    {
        var collection = _database.GetCollection<MongoEntity>("Books");
        return collection.Find(book => true).ToList();
    }

    public void AddBsonDocument()
    {
        var author = new Author()
        {
            Name = "Name",
            LastName = "Lastname",
            AuthorId = ObjectId.GenerateNewId().ToString()
        };

        var category = new Category()
        {
            CategoryId = ObjectId.GenerateNewId().ToString(),
            CategoryName = "Non-fiction"
        };

        var book = new Book()
        {
            BookName = "Random title",
            Category = category,
            Price = 54.93m,
            Added = DateTime.Now,
            BookId = ObjectId.GenerateNewId().ToString(),
            Author = author
        };

        var lib = new BookLibrary(){BookLibraryId = ObjectId.GenerateNewId().ToString(), Library = new List<Book>()};
        lib.Library.Add(book);



        var collection = _database.GetCollection<MongoEntity>("Books");

        var list = new List<MongoEntity> {lib, book, author, category};

        collection.InsertMany(list);

    }
}

2 Answers 2

3

The answer turned out to be super easy and obvious but somehow I missed it.

The type of the object is not strongly related to the collection name so I could go with:

var books = _database.GetCollection<Books>("Books");
var bookLibraries = _database.GetCollection<BookLibrary>("Books");
var authors = _database.GetCollection<Author>("Books");
var categories = _database.GetCollection<Category>("Books");

Another solution is to use BsonDocument type:

var books = _database.GetCollection<BsonDocument>("Books");

Just like that.

Sign up to request clarification or add additional context in comments.

Comments

1

The problem is with the Id field. You made it custom, but MongoDB will always store your ID property as _id inside the DB and this cannot be changed. Trying to alter the name using BsonElementAttribute will be simply ignored.

To solve your problem you can try the following:

  1. Add attribute on CategoryId (and others ids fields too) with BsonElement, but I'm not sure if it works.
  2. Change CategoryId to Id (and others ids fields too)

1 Comment

Unfortunately, none of those worked. I also noticed that on clean db it works. So, I have empty db -> adding records -> I'm able to retrieve them. When I close the app and re-run it without dropping db it gives me exception. I think the idea with empty class MongoEntity is wrong - but when getting collection I need to define the type of documents: var collection = _database.GetCollection<MongoEntity>("Books");

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.