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 中调试我的应用程序时:
- personX:ID = {5a3b81ceff702421e00c5c7e},姓名 = "John created at 131583228941663577"
- 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;
}
在 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 中调试我的应用程序时:
- personX:ID = {5a3b81ceff702421e00c5c7e},姓名 = "John created at 131583228941663577"
- 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;
}