我尝试了几种看起来彼此相同的解决方案。关于将新文档插入我的Azure Cosmos数据库的问题。我得到的错误是重复的键错误。我要完成的工作是让Azure Cosmos DB自己为我生成密钥,而不是自己必须在代码中显式创建密钥。
我在.Net逻辑中生成密钥的主要问题是.Net应用程序可能会创建重复密钥,因为它有时会短暂关闭,这可能会重置其内部服务器时钟。我不认为这会在Azure中发生,因此我希望通过在插入发生时继续生成密钥来利用这一点。
我正在使用接口模型将对象存储在Azure数据库中。
interface IExample
{
ObjectId Id { get; set; }
}
我还设计了一个具体的类来实现此接口。
public class Example : IExample
{
public ObjectId Id { get; set; }
}
我已经尝试在上面的Id字段的接口和类中使用以下属性及其组合。
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;
}
}
我想针对这个首要问题的后续问题是:
我得到的错误是E11000,没有显式创建对象ID。
编辑:更新了尝试数据注释的代码,以显示IExample的实现。
在解决了更多问题之后,并使我的API可以用于POST,PATCH和GET,我注意到使用ObjectId属性非常困难。我还发现了一个帖子,指出建议在属性的ObjectId类型上使用字符串。
序列化Mongo ObjectId第三部分ZOXEXIVO的答案时JSON.NET转换错误
将字符串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; }
}
我还更新了存储库,以通过接口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属性的知识。通过将字符串Id属性与BsonId和BsonRepresentation(BsonType.ObjectId)数据注释一起使用,CosmosDb可以为帖子中的解决方案生成唯一的键。对于将来的数据模型,我将向其他开发人员推荐此解决方案,因为它还清理了在GET中返回的这些数据模型。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句