2

I want to store the following object in azure documentdb

public class MyDocument
{
    public string Id { get; set; }
    public SomeOtherClass SomeOtherClass { get; set; }
}

the property Id is a timestamp (yyyyMMddHHmmss) followed by a guid. As a side-effect, this allows me to sort on Id. I used this call to store it:

 await docDbClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(db, coll), myDoc);

When the document is stored, it has my documents properties (Id and SomeOtherClass) and an additional "id" property (note the lowercase "i"). (and some other technical properties used by documentdb). This is filled with a guid.

As far as I understood, by storing an object which already has an Id property, documentdb would use this and not generate it's own (but it did!).

Now I have two problems: I can't check with

 await docDbClient.ReadDocumentAsync(UriFactory.CreateDocumentCollectionUri(db, coll), myDoc.Id);

to see if a document already exists, and I can't use the Id property to sort and compare documents in a query like this:

IQueryable<MyDocument> query = _client.CreateDocumentQuery<MyDocument>(
            UriFactory.CreateDocumentCollectionUri(_account.Database, _account.Collection), queryOptions);
 query = query.Where(x => x.Id.CompareTo(inputValue) >= 0);

where inputValue is another key of the same form, to be used for paging. Because when deserializing the object out of documentdb, the id property replaces my Id property and I never see it's original value.

Am I using this wrong? Did I make the wrong assumption that my Id property would be used instead of an auto-generated one with lowercase?


EDIT: I can confirm that this is solved when using [JsonProperty("id")] on the Id property. But any document already insertedI can't retrieve my original value of Id

4 Answers 4

4

The ID field is expected to be "id" lower case.

This would solve it:

[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
Sign up to request clarification or add additional context in comments.

2 Comments

Also, there are some issues with NewtonSoft.Json 10.x og CosmosDB/DocumentDB, so you should use a previous version.
Didn't work for me, I still get "Id" and "id" in the document
2

DocumentDB's id property is what has to be unique. Your own Id property (with upper-case I) is not a special property - it's just... a property that you created.

And you've seen the guids auto-generated in the id property. Note that you can put your own value in id, as long as it's unique. You don't have to accept the default value (guid).

1 Comment

I understand, but the docs say that you can specify your own value without saying that it has to be json-serialized as (lowercase) id or at least that's how I read it. And because of pascal-casing muscle memory I used Id. What's weird is that when query-ing, the Id property got filled with the contents of id and I have no way of retrieving Id
2

CosmosDb only guarantees unique id field values for the same partition key. Therefore, this can exist in the same collection:

{
    "id": "12345",
    "myPartitionKey": "A",
    ...
},
{
    "id": "12345",
    "myPartitionKey": "B", //different partition key than above
    ...
},

but this cannot exist:

{
    "id": "12345",
    "myPartitionKey": "A",
    ...
},
{
    "id": "12345",
    "myPartitionKey": "A", // Inconceivable! Same id AND partition key as above
    ...
},

Comments

0

A bit more up-to-date information: if you are using IEntityTypeConfiguration to configure the mapping, you only need to use the ToJsonProperty() method to define the name of your property.

Another tip is to use the NuGet package Humaziner to configure the property names in camelCase. For example:

public class MyDocument
{
    public string Id { get; set; }
    public SomeOtherClass SomeOtherClass { get; set; }
}

public class SomeOtherClass
{
    public string Id { get; set; }
    public string SomeProperty { get; set; }
}

public void Configure(EntityTypeBuilder<MyDocument> builder)
{
    builder.ToContainer("MyDocuments");
    builder.HasKey(x => x.Id);

    builder
        .Property(x => x.Id)
            .ToJsonProperty(
                nameof(MyDocument.Id).Camelize());

    builder.OwnsOne(
        x => x.SomeOtherClass,
        x =>
        {
            x.Property(y => y.SomeProperty)
                .ToJsonProperty(
                    nameof(SomeOtherClass.SomeProperty).Camelize());
        });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.