Paul Cavacas
Paul Cavacas

Reputation: 4454

How to update document in Azure CosmosDB in C#

I have a method that loads a document from Cosmos DB. The document is not strongly type and it cannot be strongly typed. I want to update various properties on the document and then push that document back to CosmosDB.

The problem that I'm having is that the property that I want to update is nested underneath another object and I cannot find documentation on how to navigate down to this sub property and update that.

Here is what I'm currently trying to do.

var project = await Service.GetById(projectId) as Microsoft.Azure.Documents.Document;

var gate = project.GetPropertyValue<dynamic>("IdeaInitiatedGate");
project.SetPropertyValue("IdeaInitiatedGate.VpApprovalStatus", status);
project.SetPropertyValue("IdeaInitiatedGate.VpApprovalComments", comments);
project.SetPropertyValue("IdeaInitiatedGate.VpApprovalOn", DateTime.Now);
project.SetPropertyValue("IdeaInitiatedGate.Status", status == "Approved" ? "Completed" : "Rejected");
if (status == "Approved")
{
    project.SetPropertyValue("CharterReview.Status", "Active");
}
var document = await Service.Replace(project);

Service is just wrapper around the actual CosmosDB calls. What is happening with the above code is that new property is being created in the document called "IdeaInitiatedGate.VpApprovalStatus" right at the root of the document. What I want to happen is to update the VpApprovalStatus property of the IdeaInitiatedGate to the new value.

want to update this

{
  "IdeaInitiatedGate": {
    "VpApprovalStatus": "Approved"
  }
}

not create this

{
  "IdeaInitiatedGate.VpApprovalStatus": "Approved"
}

The final working solution that I ended up with is below. Basically I use the GetPropertyValue to pull out the root object that I want, which is dynamic and then I change this object and the SetProperty value of the entire dynamic object.

if (!(await Service.GetById(projectId) is Document project)) return null;

var gate = project.GetPropertyValue<dynamic>("IdeaInitiatedGate");
gate.VpApprovalStatus = status;
gate.VpApprovalComments = comments;
gate.VpApprovalOn = DateTime.Now;
gate.Status = status == "Approved" ? "Completed" : "Rejected";
project.SetPropertyValue("IdeaInitiatedGate", gate);

if (status == "Approved")
{
    var charterGate = project.GetPropertyValue<dynamic>("CharterReview");
    charterGate.Status = "Active";
    project.SetPropertyValue("CharterReview", charterGate);
}
var result = await Service.Replace(project);

Upvotes: 2

Views: 10109

Answers (1)

Tom Sun
Tom Sun

Reputation: 24569

We could set IdeaInitiatedGate Property with a JObject

project?.SetPropertyValue("IdeaInitiatedGate", new JObject { { "VpApprovalStatus", status }});

If you want to add the mutilple property for IdeaInitiatedGate. We could do with following way.

project?.SetPropertyValue("IdeaInitiatedGate", new JObject { { "VpApprovalStatus", "Approved" },{ "VpApprovalComments", comments},{ "VpApprovalOn", DateTime.Now }});

The following is the demo code. It works correctly on my side.

var project = (Document)client.CreateDocumentQuery<dynamic>(UriFactory.CreateDocumentCollectionUri(databaseName, collectionName))
            .AsEnumerable()
            .First();
var gate = project?.GetPropertyValue<dynamic>("IdeaInitiatedGate");
project?.SetPropertyValue("IdeaInitiatedGate", new JObject { { "VpApprovalStatus", "Approved" }});
var document = client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(databaseName, collectionName, project?.Id), project).Result.Resource;

Check from the Azure Portal:

enter image description here

Upvotes: 1

Related Questions