11

I am trying to delete row from azure storage filter by only rowkey value. But I dont see any overload for delete operation where we can filter with only rowkey. Is there any alternative option to delete row from azure storage table for records with specific rowkey?

RemoveEntityByRowKey('123456');
public static void RemoveEntityByRowKey(string myRowKey)
        {
            try
            {
                CloudTable table = _tableClient.GetTableReference("MyAzureTable"); 
                       TableOperation delteOperation = TableOperation.Delete(myRowKey);
                table.Execute(delteOperation);
            }
            catch (Exception ex)
            {
                LogError.LogErrorToAzure(ex);
                throw;
            }
        }
Kurkula
  • 6,386
  • 27
  • 127
  • 202
  • [`TableOperation.Delete` is now deprecated](https://stackoverflow.com/a/69813616/542251) – Liam Nov 02 '21 at 16:13

8 Answers8

11

In order to delete an entity, you would need both PartitionKey and RowKey (Delete Entity REST API). So what you would need to do is first fetch the entity with matching RowKey. Once you have fetched this entity, you should be able to call TableOperation.Delete as mentioned in the answers.

However, fetching entity by RowKey is not recommended because it will do a Full Table Scan. It may not be a problem if your table size is small but would be an issue where your table contains large number of entities. Furthermore, a RowKey is unique in a Partition i.e. in a table there can be only one entity with a PartitionKey/RowKey combination. In other words, you can potentially have entities with same RowKey in different Partitions. So when you fetch entities by RowKey only, you may get more than one entity back. You need to ensure that you're deleting correct entity.

Gaurav Mantri
  • 128,066
  • 12
  • 206
  • 241
  • nice and interesting pointer Gaurav. Deleting records based on row key will be a bad idea? what would be the best option? – Kurkula May 13 '16 at 05:33
  • 2
    Not sure how your table is designed but the best option is where you don't have to search for an entity. If you know the PartitionKey and RowKey for an entity, you can use that to create an instance of `TableEntity` and then delete that entity. – Gaurav Mantri May 13 '16 at 05:40
  • In my case partition key is time tick which changes frequently and cannot be used for querying. That's the reason I have to query only with rowkey. – Kurkula May 13 '16 at 05:52
  • 1
    Understood...but please do realize that fetching entities just by RowKey would not be the most effective way. You mentioned that your PartitionKey is time tick. If your objective is to delete entities between certain time periods, you can include a PartitionKey range and search for RowKey in those ranges. It would be somewhat better than searching just on RowKey. HTH. – Gaurav Mantri May 13 '16 at 05:59
  • 1
    If you want to delete an entity using PartitionKey and RowKey, you also need to specify ETag "*", otherwise the API will reject the call. In Azure.Data.Tables, you can get such ETag using ETag.All static field. – Palec Feb 10 '21 at 22:37
9

If you know the PartitionKey as well as the RowKey, you don't need to retrieve the entire entity to delete it. You could adapt your code as follows:

public static void RemoveEntityByRowKey(string myRowKey)
{
    try
    {
        var entity = new YourEntity 
        {
            PartitionKey = "partition",
            RowKey = myRowKey,
            ETag = "*"
        }

        CloudTable table = _tableClient.GetTableReference("MyAzureTable"); 
        TableOperation delteOperation = TableOperation.Delete(entity);
        table.Execute(delteOperation);
    }
    catch (Exception ex)
    {
        LogError.LogErrorToAzure(ex);
        throw;
    }
}    
snow_FFFFFF
  • 3,235
  • 17
  • 29
5

If you're targeting .NET Core, you'll need to use the ExecuteQuerySegmentedAsync method to execute the filter condition query. ExecuteQuery is deprecated.

var cloudTableClient = _cloudStorageAccount.CreateCloudTableClient();
var myTable = cloudTableClient.GetTableReference("MyTable");
var query = new TableQuery<MyEntity>().Where(TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, "myRowKey"));
var segment = await myTable.ExecuteQuerySegmentedAsync(query, null);
var myEntities = segment.Results;
Sirar Salih
  • 2,514
  • 2
  • 19
  • 18
2

By row do you mean a record ?

TableOperation.Delete accepts a Table Entity. See here: https://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storage.table.tableoperation.delete.aspx

In order to delete that entity, you must first retrieve it by specifying its Partition key and/or Row key.

Look into TableQuery class here https://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storage.table.tablequery_methods.aspx

Once you retrieve it, pass it to Delete method.

Frank Q.
  • 6,001
  • 11
  • 47
  • 62
  • You really deserve bounty bonus points in 2 days. Your answer acted as useful pointer. – Kurkula May 13 '16 at 06:06
  • 3
    Both of these links unfortunately 404 now – Nathan Aug 22 '19 at 13:26
  • 2
    If you know the PartionKey and RowKey, you do NOT need to fetch the entity first. Use ```TableOperation delete = TableOperation.Delete(new TableEntity(PartitionKey, RowKey) { ETag = "*" })``` ' – MonteChristo Feb 24 '21 at 18:42
2

There is no method

TableOperation.Delete(String rowKey),

only method

public static TableOperation delete(final TableEntity entity)

in TableOperation. For details, see Get started with Azure Table storage using .NET

Alex Chen-WX
  • 521
  • 2
  • 5
  • 3
    What ?? That seems so inefficient. You have to retrieve to delete ? There has to be a better way. – micahhoover Apr 06 '19 at 16:29
  • 1
    @micahhoover Correct, you **don't** need to retrieve-to-delete: you can use a `DynamicTableEntity` and supply only the `PartitionKey` and `RowKey` values and pass that into `TableOperation.Delete` - but if you only know the `RowKey` and don't know the `PartitionKey` then you'll need to do some form of query. – Dai Jul 10 '20 at 20:11
0

With reference to Franks pointers, I am posting answer so that it would be useful to others who face the similar issue.

RemoveEntityByRowKey('123456');
public static void RemoveEntityByRowKey(string myRowKey)
        {
            try
            {
                CloudTable table = _tableClient.GetTableReference("MyAzureTable"); 

   TableQuery<myEntity> query = new TableQuery<myEntity>()
                   .Where(TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, myRowKey));

                foreach (var item in table.ExecuteQuery(query))
                {
                    var oper = TableOperation.Delete(item);
                    table.Execute(oper);                    
                } 
            }
            catch (Exception ex)
            {
                LogErrorToAzure(ex);
                throw;
            }
        }
Kurkula
  • 6,386
  • 27
  • 127
  • 202
  • 1
    Though the approach is correct I don't think your design might be. In table queries you must try to avoid Table Scan (scanning almost entire table which is what I believe you are doing here) or Partition Scan (specifying partition scan and another key other than rowkey). Range Query (specifying partition and some range of rowkey) is better and Point query is the best. – Frank Q. May 13 '16 at 17:13
0

mpl is my table row entity and is required to delete the record from the db. I have added this answer to show an async (with result check)

           if (result)
            {
                //delete the lead from the storage table
                TableOperation delRow = TableOperation.Delete(mpl);
                TableResult tr = await table.ExecuteAsync(delRow);
                if (((int)tr.HttpStatusCode) < 400)
                    log.LogInformation($"Table Record: {mpl.RowKey} deleted");
                else
                    log.LogError($"Table Record: {mpl.RowKey} NOT deleted");

            }
Lodlaiden
  • 361
  • 1
  • 10
0

The Windows.Azure.Storage namespace is now deprecated in favour of the Azure.Data.Tables namespace. As such the TableOperation.Delete method is also deprecated. You should now use a TableClient and it's DeleteEntity method:

TableClient tableClient = new TableClient(connectionString, Table);
tableClient.DeleteEntity(PartitionKey, RowKey);

There is also the async version DeleteEntityAsync if you wish too.

RoadRunner
  • 25,803
  • 6
  • 42
  • 75
Liam
  • 27,717
  • 28
  • 128
  • 190