This question had been asked many times and even answered correctly a few times, I've seen them all, and yet, it happens to me no matter what I do. Here is the code:
Creating container:
string partitionKeyPath = $"/{_userId}";
_container = await database.CreateContainerIfNotExistsAsync(_containerName, partitionKeyPath);
Then when the time comes to add my Chat object:
if (_container != null)
{
Chat? chat;
bool newChatCreated = false;
try
{
// Attempt to read the Chat item. If it exists, add the ChatItem to it.
chat = await _container.ReadItemAsync<Chat>(chatId, new PartitionKey(_userId)).ConfigureAwait(false);
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
// If the Chat item does not exist, create a new one.
chat = new Chat
{
id = chatId,
_userId = _userId,
ChatItems = new List<ChatItem>(),
ChatName = chatName,
IndexName = indexName,
TimeCreated = DateTime.Now.ToString("yyyy/MM/dd-HH:mm:ss.fff")
};
ContainerProperties props = await _container.ReadContainerAsync();
_logger.LogInformation($"PartitionKeyPath: {props.PartitionKeyPath}");
// Exception happens on the next line in CreateItemAsync !!!
await _container.CreateItemAsync<Chat>(chat, new PartitionKey(_userId));
newChatCreated = true;
}
chat?.ChatItems?.Add(chatItem);
if (newChatCreated)
{
// Update the Chat item in the database
await _container.ReplaceItemAsync<Chat>(chat, chatId, new PartitionKey(_userId));
}
else
{
var patchOperations = new List<PatchOperation>
{
PatchOperation.Add("/ChatItems/-", chatItem)
};
await _container.PatchItemAsync<Chat>(chatId, new PartitionKey(_userId), patchOperations);
}
}
else
{
_logger.LogError("_container is null");
return false;
}
The _userId that serves as the PartitionKey is all alphanumeric small case: "supportgpt4officecom". The PartionKeyPath is the same but prepended with '/', that is: "/supportgpt4officecom" (verified by logging it just before the call.)
So, is anybody can explain to me what's going on? BTW, I am running the latest CosmosDB version: Microsoft.Azure.CosmosDB 3.37.1
string partitionKeyPath = $"/{_userId}";
The Container's Partition Key Definition should have the name of the property and its path, not the value.
For example, let's say your Document has the _userId
property, then it should be:
string partitionKeyPath = "/_userId";
When you do the item operations, you then, as you are doing correctly, pass the Partition Key Value which is, the value of the _userId
property for that Document.
If the property name is not _userId
just alter the code for the correct property name.