azure-cosmosdb - Cosmos DB 对数据库的分区访问
问题描述
我正在使用 cosmosDB 实现一个多租户应用程序。我正在使用分区键来分隔多个用户数据。遵循最佳实践,我试图让每个租户都有自己的数据库访问令牌。
我创建了一个用户和权限,并使用创建的令牌来访问分区。但我收到以下错误:
提供的分区键与集合中的定义不对应,或者与文档中指定的分区键字段值不匹配。ActivityId:1659037a-118a-4a2d-8615-bb807b717fa7,Microsoft.Azure.Documents.Common/1.22.0.0,Windows/10.0.17134 documentdb-netcore-sdk/1.9.1
我的代码如下:
构造函数启动客户端
public Projects (CosmosDbConfig cosmosConfig)
{
config = cosmosConfig;
client = new DocumentClient(new Uri(config.Endpoint), config.AuthKey);
collectionUri = UriFactory.CreateDocumentCollectionUri(config.Database, config.Collection);
config.AuthKey = GetUserToken().Result;;
client = new DocumentClient(new Uri(config.Endpoint), config.AuthKey);
}
get user 函数创建用户并检索令牌。用户 ID 是分区键。
private async Task<string> GetUserToken()
{
User user = null;
try
{
try
{
user = await client.ReadUserAsync(UriFactory.CreateUserUri(config.Database, config.PartitionKey));
var permission = await GetorCreatePermission(user, config.Collection, config.PartitionKey);
return permission.Token;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
if (user == null)
{
user = new User
{
Id = config.PartitionKey
};
user = await client.CreateUserAsync(UriFactory.CreateDatabaseUri(config.Database), user);
var permission = await GetorCreatePermission(user, config.Collection, config.PartitionKey);
return permission.Token;
}
else
{
throw new Exception("");
}
}
catch (Exception ex)
{
throw ex;
}
}
权限是按集合完成的,并将集合名称作为 ID 保存,因为每个用户的 ID 都是唯一的。
private async Task<Permission> GetorCreatePermission(User user,
string collection,
string paritionKey)
{
var permDefinition = new Permission
{
Id = collection,
PermissionMode = PermissionMode.All,
ResourceLink = collectionUri.OriginalString,
ResourcePartitionKey = new PartitionKey(paritionKey),
};
var perms = client.CreatePermissionQuery(user.PermissionsLink).AsEnumerable().ToList();
var perm = perms.FirstOrDefault(x => x.Id == collection);
if (perm != null)
{
return perm;
}
else
{
var result = await client.CreatePermissionAsync(user.SelfLink, permDefinition);
perm = result.Resource;
return perm;
}
}
create 函数利用了新的客户端和发生错误的地方。
public async Task<string> Create(Project p)
{
var result = await client.CreateDocumentAsync(collectionUri, p, new RequestOptions()
{ PartitionKey = new PartitionKey(config.PartitionKey),
});
var document = result.Resource;
return document.Id;
}
解决方案
由于错误表明分区键不正确,我建议您在创建集合时尝试定义分区键路径:
var docCollection = new DocumentCollection();
docCollection.Id = config.CollectionName;
docCollection.PartitionKey.Paths.Add(string.Format("/{0}", config.PartitionKey );
collectionUri = UriFactory.CreateDocumentCollectionUri(config.Database, docCollection);
推荐阅读
- mysql - 一个计费周期内的多次定期收费
- openedge - Progress 4GL:如何找到定义过程的位置
- python - ZMQ连接和推送——如何判断是否失败
- android - 布尔 java.util.List.add(java.lang.Object)
- r - R中的PCA,使得第一个特征向量是常数向量
- python - 在 setup.py build 中包括来自项目根目录的 python 文件
- javascript - 使用 cookie 每天显示一次弹出窗口
- html - 结合 flex 和 position:fixed
- swift4 - 使用 alamofire 上传图像显示此问题(原因:Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)
- javascript - 使用反应如何获取保存在 const 中的选择下拉列表的值?