haPartnerships
haPartnerships

Reputation: 385

Azure Table TableClient Response - ETag

Posted a few variations of a theme on this question but don't seem to have asked the right question and have also dug more into my problem.

So...

I am querying Azure Table Storage using the Azure.Data.Table TableClient with the GetEntityAsync<Type>(partitionKey, rowKey) method


Update - TableClient Calling Code

using the following code:

Initialize the tableclient:

public AzureTableService(string tableName, string storageUri, string accountName, string storageAccountKey) 
{
         tableClient  = new TableClient(
         new Uri(storageUri),
         tableName,
         new TableSharedKeyCredential(accountName, storageAccountKey));
}

Get the TableEntity

public async Task<TableEntity> GetEntityAsync(string partitionKey, string rowKey) 
{
        var response = await tableClient.GetEntityAsync<TableEntity>(partitionKey, rowKey);
        return response.Value;
}

in two ways:

  1. With TableEntity as the type
  2. With User as the type

TableEntity is the type Azure.Data.Table.TableEntity which itself inherits Azure.Data.Table.ITableEntity. ITableEntity defines the properties ETag Etag, string PartitionKey, string RowKey, and DateTimeoOffset? Timestamp.

User is a class which inherits from ITableEntity and therefore has those same properties alongside strings for Forename, Surname, Mobile and Address.


Update - User Object Definition

public class User : ITableEntity
{
    public User() { }
    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public DateTimeOffset? Timestamp { get; set; }
    public ETag ETag { get; set; }
    public string Forename { get; set; }
    public string Surname { get; set; }
    public string Mobile { get; set; }
    public string Address { get; set; }

}

As such both are valid to use as the type for the method GetEntityAsync<type> as they both implement the same interface.

If I use the User type the returned object serialised as Json is:

{
    "partitionKey": "partitionKey",
    "rowKey": "rowKey",
    "timestamp": "2023-02-09T22:28:54.0242121+00:00",
    "eTag": {},
    "forename": "forename",
    "surname": "surname",
    "mobile": "mobile",
    "address": "address"
}

If I use the TableEntity type the returned object serialised as Json is:

{
    "odata.etag": "W/\"datetime'2023-02-09T22%3A28%3A54.0242121Z'\"",
    "PartitionKey": "partitionKey",
    "RowKey": "rowKey",
    "Timestamp": "2023-02-09T22:28:54.0242121+00:00",
    "Address": "address",
    "Forename": "forename",
    "Mobile": "mobile",
    "Surname": "surname"
}

Neither is populating the ETag correctly - User has a value of ETag: {} and TableEntity has a valid string value of an ETag "W/\"datetime'2023-02-09T22%3A28%3A54.0242121Z'\"" BUT it is is a string with a property name of odata.etag NOT an object of type ETag named ETag as per the ITableEntity implementation.

Further to this...

when I do a delete operation and require the ETag ifMatch for validation the validation works using the odata.etag property value and seemingly not using the ETag property as implemented with ITableEntity.


Update - Delete Method

public async Task<bool> DeleteItemAsync(TableEntity item, bool forceDelete)
{
        var response = await tableClient.DeleteEntityAsync(item.PartitionKey, item.RowKey, forceDelete? ETag.All : item.ETag);
        if (response.Status == 200 || response.Status == 201 || response.Status == 204) { return true; }
        else { throw new Exception($"The response was {response.Status} - {response.ReasonPhrase}"); }
}

So in effect - the ITableEntity implements a property ETag that is not being set and does not support the ETag property for validation.

I am SO confused - what do I need to do to get the ITableEntity ETag property assigned using the Azure.Data.Table.GetEntityAsync<TableEntity>(PK, RK) method and used in the Azure.Data.Table.DeleteEntityAsync(PK, RK, ETag) validation?

Upvotes: 3

Views: 1851

Answers (0)

Related Questions