1

I'm new to CosmosDB and trying to figure out what's going on. I am using Microsoft.Azure.Cosmos NuGet package for development.

This is the line that creates my container:

Container = await database.CreateContainerIfNotExistsAsync(Program.ContainerId, "/id", 400)

This is my class:

     public class REProperty
     {
        public const string PartitionKey = "id";

        [JsonProperty(PropertyName = "id")]
        public string Id { get; set; }

        public string Number { get; set; }

        public User Owner { get; set; }

And finally the code where I try to create a new document:

ItemResponse<REProperty> Response = await Program.Container.CreateItemAsync<REProperty>(C, new PartitionKey(REProperty.PartitionKey));

I am using the exact same PartitionKey everywhere yet I am still getting this error every time. Am I missing anything obvious?

Error message: (Message: {"Errors":["PartitionKey extracted from document doesn't match the one specified in the header"]

Matt Small
  • 2,182
  • 1
  • 10
  • 16

1 Answers1

3

You've defined the collection to use the id property as the partition key. The value given as id will then be the partition key used. However, you are specifying this:

ItemResponse<REProperty> Response = await Program.Container.CreateItemAsync<REProperty>(C, new PartitionKey(REProperty.PartitionKey));

This will always set the value "id" as the partition key, which is not correct. The actual value is different from document to document. So either you set it like this: new PartitionKey(C.Id) or you just omit the partition key part in the item creation - I think it should be enough to just have the property set, but give it a try to check it.

DSpirit
  • 2,062
  • 16
  • 22
  • It worked great to remove the PartitionKey, thank you! However, I am confused by it. I see that I am required to add it in the delete code. Is C.ID the correct parameter to pass(I haven't tested yet). ItemResponse caseResponse = await Program.caseContainer.DeleteItemAsync(C.Id, new PartitionKey(C.Id)); – Matt Small Oct 29 '20 at 14:59
  • 1
    Glad to hear it worked :) Yes, that would be the right code to use for deleting the document in your case. As you've chosen _id_ to be the partition key, every document is stored in a separate partition (which is quite inefficient though). Therefore you delete a document by id and its corresponding partition, which happens to be _id_, too. If you have a collection with employees and let's say _division_ as a partition key, you'd have fewer partitions - e.g. 2 employees are _management_, 5 are _sales_ and 3 are _delivery_. – DSpirit Oct 29 '20 at 15:05
  • That was my original intent. I got confused by the sample I was using because it made it seem that an identical partition id was defining the group of like items. But what you're saying is that I could have a separation of documents by a property called "type" and each type is one of three values - this would divide my documents based on the value of type and I would have better performance. Is that correct? – Matt Small Oct 29 '20 at 15:10
  • 1
    Oh I know that thought very well. Exactly, if you decide you to use _type_ as the partition key, every different _type_ value provided will create a separate partition. This will be way more efficient than the _id_ type, but if you want to access documents e.g. by id, you'll always need the corresponding type (= partition key) value to acquire it. If you don't know the partition key, you'll need to execute a query with _enableCrossPartitionQuery_ parameter set to true. – DSpirit Oct 29 '20 at 15:15
  • 1
    Check this for more information: https://learn.microsoft.com/en-us/azure/cosmos-db/partitioning-overview – DSpirit Oct 29 '20 at 15:23