How to delete a Durable Entity
Tags: azurefunctions, durablefunctions, durableentities
Published: 2023-01-18 09:48:00

In this post I would like to show you how you can delete a Durable Entity in your solution.
Probably you don't know, but that functionality is built-in in the Durable Functions platform.
Suppose we have the definition of our entity (a counter):

```csharp
public interface ICounter
{
    void Increment();
}
```

and one implementation of our counter:

```csharp
public class MyCounter : ICounter
{
    private readonly ILogger _logger;
    public MyCounter(ILogger logger)
    {
        _logger = logger;
    }

    public int Count { get; set; } = 0;

    public void Increment()
    {
        _logger.LogInformation($"Increment counter {Entity.Current.EntityKey}");
        Count++;
    }

    [FunctionName(nameof(MyCounter))]
    public static Task Run([EntityTrigger] IDurableEntityContext ctx, ILogger logger)
        => ctx.DispatchAsync<MyCounter>(logger);
}
```
We can manage our counters using a simple client function like the following:

```csharp
public class IncrementCounterClient
{
    private readonly ILogger _logger;

    public IncrementCounterClient(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<IncrementCounterClient>();
    }

    [FunctionName("IncrementCounter")]
    public async Task<IActionResult> Run(
       [HttpTrigger(AuthorizationLevel.Function, "get", Route = "counters/{counterName}")] HttpRequest req,
       string counterName,
       [DurableClient] IDurableEntityClient client)
    {
        _logger.LogInformation("IncrementCounter function");
        IActionResult responseData = null;

        var entityId = new EntityId(nameof(MyCounter), counterName);

        await client.SignalEntityAsync<ICounter>(entityId, entity => { entity.Increment(); });

        return responseData;
    }
}
```
Using the API exposed by the previous client we can increment a counter with a simple Get request like the following:

```bash
curl http://localhost:7214/api/counters/counter01
```

If you are testing your functions locally, you can see the traces in the Azure Functions debug console:

![The Azure Functions console during the counter increment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tc2a77hzqi64ms685lab.png)

The operation changes the status of the entity in memory, and then, into the local storage account and you can see it opening the Storage Explorer tool and look at the HubInstances table:

![The entities history table in the local storage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eohn11f68te3x3novn3y.png)

If we open the row with partition key `@mycounter@counter01`, we can see the status of the entity (in the `input` column) and also we can have the information that the Entity exists in the column called `CustomStatus`:

![The entity property values](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/27atr26xlpawwf02gauo.png)

Now, if we want to delete the entity, we can use the built-in `delete` operation.
The Durable Entities platform provides us with built-in APIs to manage entities. In particular, if we want to perform an operation of a particular entity (for example our Increment), we can use the following API:

```http
POST /runtime/webhooks/durabletask/entities/{entityName}/{entityKey}
    ?op={operationName}
```

In our scenario, `entityName` is `mycounter`, `entityKey` is `counter01` and `op` is `increment`.

```bash
curl -X POST  http://localhost:7214/runtime/webhooks/durabletask/entities/mycounter/counter01?op=increment
```

You can find more info about this features in the [official documentation](https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-http-api#request-10).
If we set `op=delete` (even if we didn't define the `delete` method in our entity interface), we have this result:

![The entity property values after the delete](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u9q547xdww8ef0asvkod.png)

As we can see, the `CustomStatus` value is changed and the internal state of the entity is empty.
The entity row is still there, but for the platform the entity is deleted. If you try to retrieve the entity using the `ListEntitiesAsync` methods (of the `IDurableEntityClient` interface), you don't find the entity previously deleted.

If you define a `delete` method in your entity (you can implement it directly in the entities without define in the interface), that method will be called when you try to post the `op=delete` operation and you can manage the deletion by yourself (using, for example, the `Entity.Current.DeleteState()` method inside your entity).