Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to obtain ETag for individual document when using FeedResponse from Microsoft.Azure.Cosmos

I'm looking at samples from https://github.com/Azure/azure-cosmos-dotnet-v3/blob/dc3468bd5ce828e504ddef92ef792c35370de055/Microsoft.Azure.Cosmos.Samples/Usage/ItemManagement/Program.cs#L590

Here is the example of using ETag when using container.ReadItemAsync:

            ItemResponse<SalesOrder> itemResponse = await container.ReadItemAsync<SalesOrder>(
                partitionKey: new PartitionKey("Account1"),
                id: "SalesOrder1");

            Console.WriteLine("ETag of read item - {0}", itemResponse.ETag);

            SalesOrder item = itemResponse;
            //Update the total due
            itemResponse.Resource.TotalDue = 1000000;

            //persist the change back to the server
            ItemResponse<SalesOrder> updatedDoc = await container.ReplaceItemAsync<SalesOrder>(
                partitionKey: new PartitionKey(item.AccountNumber),
                id: item.Id,
                item: item);

            Console.WriteLine("ETag of item now that is has been updated - {0}", updatedDoc.ETag);

            //now, using the originally retrieved item do another update 
            //but set the AccessCondition class with the ETag of the originally read item and also set the AccessConditionType
            //this tells the service to only do this operation if ETag on the request matches the current ETag on the item
            //in our case it won't, because we updated the item and therefore gave it a new ETag
            try
            {
                itemResponse.Resource.TotalDue = 9999999;
                updatedDoc = await container.ReplaceItemAsync<SalesOrder>(itemResponse, item.Id, new PartitionKey(item.AccountNumber), new ItemRequestOptions { IfMatchEtag = itemResponse.ETag });
            }
            catch (CosmosException cre)
            {
                //   now notice the failure when attempting the update 
                //   this is because the ETag on the server no longer matches the ETag of doc (b/c it was changed in step 2)
                if (cre.StatusCode == HttpStatusCode.PreconditionFailed)
                {
                    Console.WriteLine("As expected, we have a pre-condition failure exception\n");
                }
            }

In my scenario I have a query and I need to obtain ETag for later use in Update. In this sample we get FeedResponse<SalesOrder> which has ETag, but this is the tag associated with last transaction, not document. So my question is how to get ETag of an individual document?

        private static async Task QueryItems()
        {
            //******************************************************************************************************************
            // 1.4 - Query for items by a property other than Id
            //
            // NOTE: Operations like AsEnumerable(), ToList(), ToArray() will make as many trips to the database
            //       as required to fetch the entire result-set. Even if you set MaxItemCount to a smaller number. 
            //       MaxItemCount just controls how many results to fetch each trip. 
            //******************************************************************************************************************
            Console.WriteLine("\n1.4 - Querying for a item using its AccountNumber property");

            QueryDefinition query = new QueryDefinition(
                "select * from sales s where s.AccountNumber = @AccountInput ")
                .WithParameter("@AccountInput", "Account1");

            FeedIterator<SalesOrder> resultSet = container.GetItemQueryIterator<SalesOrder>(
                query,
                requestOptions: new QueryRequestOptions()
                {
                    PartitionKey = new PartitionKey("Account1"),
                    MaxItemCount = 1
                });

            List<SalesOrder> allSalesForAccount1 = new List<SalesOrder>();
            while (resultSet.HasMoreResults)
            {
                FeedResponse<SalesOrder> response = await resultSet.ReadNextAsync();
                SalesOrder sale = response.First();
                Console.WriteLine($"\n1.4.1 Account Number: {sale.AccountNumber}; Id: {sale.Id};");
                if(response.Diagnostics != null)
                {
                    Console.WriteLine($" Diagnostics {response.Diagnostics.ToString()}");
                }

                allSalesForAccount1.Add(sale);
            }
like image 641
Fuczak Avatar asked Nov 28 '25 15:11

Fuczak


1 Answers

When you execute a query, the FeedResponse contains a list of objects of type T. You can obtain the ETag if the T contains a property that matches with the _etag system property. Source Github issue comment.

For instance, using NewtonSoft.JSON's JsonProperty attribute, I had to add the following property to my type T

[JsonProperty("_etag")]
public string ETag { get; set; }
like image 199
mrwnt10 Avatar answered Nov 30 '25 03:11

mrwnt10



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!