Как получить ETag для отдельного документа при использовании FeedResponse от Microsoft. Azure .Cosmos - PullRequest
1 голос
/ 25 мая 2020

Я смотрю образцы из https://github.com/Azure/azure-cosmos-dotnet-v3/blob/dc3468bd5ce828e504ddef92ef792c35370de055/Microsoft.Azure.Cosmos.Samples/Usage/ItemManagement/Program.cs#L590

Вот пример использования ETag при использовании контейнера .ReadItemAsyn c:

            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");
                }
            }

В моем сценарии у меня есть запрос, и мне нужно получить ETag для последующего использования в обновлении. В этом примере мы получаем FeedResponse<SalesOrder> с ETag, но это тег, связанный с последней транзакцией, а не с документом. Итак, у меня вопрос, как получить ETag отдельного документа?

        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);
            }

Ответы [ 2 ]

0 голосов
/ 25 мая 2020

Я нашел решение. Не идеально, поскольку я называю JObject.ToObject<T> дважды для:

  • SalesOrder - бизнес-объект
  • ETagCosmosDocument - объект с ETag
public class ETagCosmosDocument
{
    public string _etag {get; set;}
}

public class CosmosDocument<T>
{
    public T Document {get; private set;}
    public string ETag {get; private set;}

    public CosmosDocument(T document, string etag)
    {
        Document = document;
        ETag = etag;
    }

    public static implicit operator CosmosDocument<T> (JObject o)
    {
        T document = o.ToObject<T>();
        ETagCosmosDocument etagDoc = o.ToObject<ETagCosmosDocument>();

        return new CosmosDocument<T>(document, etagDoc._etag);
     }
}

затем используйте FeedIterator<dynamic> вместо FeedIterator<SalesOrder>

QueryDefinition query = new QueryDefinition(...)

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

while (resultSet.HasMoreResults)
{   
    FeedResponse<dynamic> response = await resultSet.ReadNextAsync();

    JObject r = response.First();
    CosmosDocument<SalesOrder> cd = r;
    ...
}
0 голосов
/ 25 мая 2020

etag - это свойство объекта ответа. Можно получить вот так.

string etag = response.ETag;

Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...