前言
我尝试了几种看起来彼此相同的解决方案。我在将新文档插入 Azure Cosmos DB 时遇到问题。 我收到的错误是重复 key 错误。我想要完成的是让 Azure Cosmos DB 为我自己生成 key ,而不是我自己必须显式创建 key 在代码中。
我对在 .Net 逻辑中生成 key 的主要担忧是我的 .Net 应用程序创建重复 key 的可能性,因为它有时会短暂关闭,这可能会重置其内部服务器时钟。我不相信这种情况会在 Azure 中发生,因此我希望利用这一点,让它在发生插入时继续生成 key 。
简单代码示例
我正在使用接口(interface)模型将我的对象存储在 Azure 数据库中。
interface IExample
{
ObjectId Id { get; set; }
}
我还有一个设计实现此接口(interface)的具体类。
public class Example : IExample
{
public ObjectId Id { get; set; }
}
尝试数据注释的示例
我已尝试在上面的 Id 字段的接口(interface)和类中使用以下属性及其组合。
interface IExample
{
[BsonId]
ObjectId Id { get; set; }
}
public class Example : IExample
{
[BsonId]
public ObjectId Id { get; set; }
}
interface IExample
{
[DatabaseGenerated(DatabaseGeneratedOption.Calculated)]
ObjectId Id { get; set; }
}
public class Example : IExample
{
[DatabaseGenerated(DatabaseGeneratedOption.Calculated)]
public ObjectId Id { get; set; }
}
interface IExample
{
[BsonId, DatabaseGenerated(DatabaseGeneratedOption.Calculated)]
ObjectId Id { get; set; }
}
public class Example : IExample
{
[BsonId, DatabaseGenerated(DatabaseGeneratedOption.Calculated)]
public ObjectId Id { get; set; }
}
当我让集合对象插入模型时,这些组合似乎都没有告诉 CosmosDB Id 应该由自己生成。
存储库示例
以下是我当前在将文档插入到存储库文件中的集合中时正在处理的内容。
private ICosmosExampleDBContext _dbContext { get; set; }
private readonly IMongoCollection<IExample> _collection;
public ExampleRepository(ICosmosExampleDBContext dbContext, IOptions<ExampleOptions> options)
{
this._dbContext = dbContext;
this._collection = this._dbContext.GetCollection<IExample>(options.Value.Collection);
}
public void CreateExample(IExample example)
{
try
{
// A duplicate key error is created if I don't explicitly create the key here.
// E11000 is encountered without this, even with above data annotations.
example.Id = MongoDB.Bson.ObjectId.GenerateNewId();
this._collection.InsertOne(example);
}
catch(Exception e)
{
throw e;
}
}
我想我对这个首要问题的后续问题是:
- 我想让 Cosmos DB 生成我的 key 是否错误?
- 我是否应该继续显式创建 key ,而不是希望 CosmosDB 为我生成 key ?
我收到的错误是 E11000,没有显式创建对象 ID。
编辑:更新了尝试数据注释的代码,以显示 IExample 的实现。
最佳答案
经过进一步的开发和研究
在对解决方案进行了更多研究并让我的 API 可用于 POST、PATCH 和 GET 后,我注意到使用 ObjectId 属性非常困难。我还发现一篇文章指出,建议在属性的 ObjectId 类型上使用字符串。
JSON.NET cast error when serializing Mongo ObjectId 第三部分ZOXEXIVO的回答
将字符串 Id 字段与 [BsonId, BsonRepresentation(BsonType.ObjectId)] 数据注释结合使用,允许 CosmosDB 在输入时自行生成键。我更新了我的数据模型以使用以下内容作为其 Id 属性。
示例代码
public interface IExample
{
public string Id { get; set; }
}
public class Example : IExample
{
[BsonId, BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
}
存储库
我还更新了我的存储库,以通过接口(interface) IExample 使用具体类 Example。这允许我在 Startup.cs 中将我的数据类型注册为 Bson 文档。
private ICosmosExampleDBContext _dbContext { get; set; }
private readonly IMongoCollection<Example> _collection;
public ExampleRepository(ICosmosExampleDBContext dbContext, IOptions<ExampleOptions> options)
{
this._dbContext = dbContext;
this._collection = this._dbContext.GetCollection<Example>(options.Value.Collection);
}
public void CreateExample(Example example)
{
try
{
// Since Id is now a string, when it is empty, it gets populated for me.
// example.Id = MongoDB.Bson.ObjectId.GenerateNewId();
this._collection.InsertOne(example);
}
catch(Exception e)
{
throw e;
}
}
摘要
总的来说,解决与我的方法相关的问题的结果使我了解了如何在我的类中使用字符串 Id 属性。将 string Id 属性与 BsonId 和 BsonRepresentation(BsonType.ObjectId) 数据注释结合使用,使我的 CosmosDb 能够为我的帖子解决方案生成唯一键。对于 future 的数据模型,我会向其他开发人员推荐此解决方案,因为它还可以清理在 GET 上返回这些数据模型的过程。
关于.net - 在 .Net Core 3.1 中使用 MongoDB API 出现 Azure Cosmos DB 中的重复 key 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61816248/