In an ASP.NET Core application (with MongoDb) I am trying to retrieve a document that I just created before.
Here is my document (POCO):
public class Person
{
[BsonId]
public ObjectId Id { get; }
public string Name { get; set; }
public Person()
{
this.Id = ObjectId.GenerateNewId();
}
}
My ASP.NET Core controller:
public class HomeController : Controller
{
private readonly IMongoDbContext _context;
public HomeController(IMongoDbContext context)
{
_context = context;
}
public async Task<IActionResult> Index()
{
var repository = new Repository(_context);
var personX = await repository.CreatePersonAsync(name: "John created at " + DateTime.Now.ToFileTimeUtc());
var personY = await repository.GetPersonByIdAsync(personX.Id);
return View();
}
}
Finally in my repository class:
public async Task<Person> CreatePersonAsync(string name)
{
var person = new Person() { Name = name };
var filter = Builders<Person>.Filter.Eq("_id", person.Id);
var saveResult = await this.PersonCollection.ReplaceOneAsync(filter, person, new UpdateOptions { IsUpsert = true });
return person;
}
public async Task<Person> GetPersonByIdAsync(ObjectId id)
{
var person = await this.PersonCollection.Find(x => x.Id.Equals(id)).FirstOrDefaultAsync();
return person;
}
When debugging my application in Visual Studio 2017 CE:
While the Name values are identical, the Ids are slightly different. Why? What am I missing?
It's probably something about async/await that I messed up, because everything works fine if I do everything synchronously.
Thanks for any help, guys!
ASP.NET Core 2, MongoDb.Driver 2.5
The problem is in your Person
class. Id
property does not have a setter, it's just initialized in constructor with value of ObjectId.GenerateNewId()
. That's why when GetPersonByIdAsync()
is called, MongoDB driver could not fill Id
property with value stored in the database and it's filled with new id generated with ObjectId.GenerateNewId()
.
To fix the problem add a public setter to Id
property. I also suggest not to fill it in constructor. Just fill it when you create new Person
instance for adding to the database:
public class Person
{
[BsonId]
public ObjectId Id { get; set; }
public string Name { get; set; }
}
public async Task<Person> CreatePersonAsync(string name)
{
var person = new Person()
{
Id = ObjectId.GenerateNewId(),
Name = name,
};
var filter = Builders<Person>.Filter.Eq("_id", person.Id);
var saveResult = await this.PersonCollection.ReplaceOneAsync(filter, person, new UpdateOptions { IsUpsert = true });
return person;
}