Save/Read 之后的错误文档 ID

Wrong document ID after Save/Read

在 ASP.NET 核心应用程序(MongoDb)中,我正在尝试检索我之前刚刚创建的文档。

这是我的文档 (POCO):

public class Person
{
    [BsonId]
    public ObjectId Id { get; }

    public string Name { get; set; }

    public Person()
    {
        this.Id = ObjectId.GenerateNewId();
    }
}

我的ASP.NET核心控制器:

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();
    }
}

终于在我的存储库中 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;
    }

在 Visual Studio 2017 CE 中调试我的应用程序时:

  1. personX:ID = {5a3b81ceff702421e00c5c7e},姓名 = "John created at 131583228941663577"
  2. personY:ID = {5a3b81ceff702421e00c5c7f},姓名 = "John created at 131583228941663577"

虽然名称值相同,但 ID 略有不同。 为什么?我错过了什么?

这可能是我搞砸了 async/await 的问题,因为如果我同步执行所有操作,一切都会正常进行。

感谢大家的帮助!

ASP.NET核心2,MongoDb.Driver2.5

问题出在您的 Person class 上。 Id 属性 没有 setter,它只是在构造函数中初始化为 ObjectId.GenerateNewId()。这就是为什么当 GetPersonByIdAsync() 被调用时,MongoDB 驱动程序无法用存储在数据库中的值填充 Id 属性,而是用 ObjectId.GenerateNewId() 生成的新 ID 填充它。

要解决此问题,请将 public setter 添加到 Id 属性。我还建议不要在构造函数中填写它。创建新的 Person 实例以添加到数据库时只需填写它:

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;
}