I have created a .net 8 isolated function app as a POC for using durable entities containing a single entity. Also created 2 endpoints, one to retrieve the entity value, the other to act on the entity. When retrieving the value of the entity it is always null. I have left the app running overnight to see if it is a timing issue and the value is still returned as null. I have tried this both running on Azureite as well a storage account in Azure.
The entity function is recognized by the framework but a breakpoint inside the function is never hit.
The code below is scraped directly from the MS documentation on Durable Entities. here
Entity Definition:
public class Counter : TaskEntity<int>
{
readonly ILogger logger;
public Counter(ILogger<Counter> logger)
{
this.logger = logger;
}
public void Add(int amount)
{
this.State += amount;
}
public Task Reset()
{
this.State = 0;
return Task.CompletedTask;
}
public Task<int> Get()
{
return Task.FromResult(this.State);
}
// Delete is implicitly defined when defining an entity this way
[Function(nameof(Counter))]
public static Task Run([EntityTrigger] TaskEntityDispatcher dispatcher)
=> dispatcher.DispatchAsync<Counter>();
}
Function Definitions:
[Function("GetCounter")]
public static async Task<HttpResponseData> GetCounter(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "Counter/{entityKey}")] HttpRequestData req,
[DurableClient] DurableTaskClient client, string entityKey)
{
var entityId = new EntityInstanceId("Counter", entityKey);
EntityMetadata<int>? entity = await client.Entities.GetEntityAsync<int>(entityId);
HttpResponseData response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync(entity?.State);
return response;
}
[Function("AddCounter")]
public static async Task<HttpResponseData> AddCounter(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "Counter/{entityKey}/add")] HttpRequestData req,
[DurableClient] DurableTaskClient client, string entityKey)
{
var entityId = new EntityInstanceId("Counter", entityKey);
await client.Entities.SignalEntityAsync(entityId, "add", 1);
HttpResponseData response = req.CreateResponse(HttpStatusCode.OK);
return response;
}
csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.1.3" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.0" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
</ItemGroup>
</Project>
Your code worked fine for me.
As I mentioned in comment and I am using DurableTask
Version 1.1.1
.
I tried using 1.1.3
was also facing the similar issue. It is becuase of package support with other packages.
I tried upgrading the other packages also but all throw some error. Packages are not compatible with each other.
I would suggest using 1.1.1
or 1.1.2
, with these versions of other packages.
This Worked for me.
Function.cs
:
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.DurableTask;
using Microsoft.DurableTask.Client;
using Microsoft.DurableTask.Client.Entities;
using Microsoft.DurableTask.Entities;
using Microsoft.Extensions.Logging;
using System.Net;
namespace FunctionApp9
{
public static class Function1
{
[Function("GetCounter")]
public static async Task<HttpResponseData> GetCounter(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "Counter/{entityKey}")] HttpRequestData req,
[DurableClient] DurableTaskClient client, string entityKey)
{
var entityId = new EntityInstanceId("Counter", entityKey);
EntityMetadata<int>? entity = await client.Entities.GetEntityAsync<int>(entityId);
HttpResponseData response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync(entity?.State);
return response;
}
[Function("AddCounter")]
public static async Task<HttpResponseData> AddCounter(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "Counter/{entityKey}/add")] HttpRequestData req,
[DurableClient] DurableTaskClient client, string entityKey)
{
var entityId = new EntityInstanceId("Counter", entityKey);
await client.Entities.SignalEntityAsync(entityId, "add", 1);
HttpResponseData response = req.CreateResponse(HttpStatusCode.OK);
return response;
}
}
public class Counter : TaskEntity<int>
{
readonly ILogger logger;
public Counter(ILogger<Counter> logger)
{
this.logger = logger;
}
public void Add(int amount)
{
this.State += amount;
}
public Task Reset()
{
this.State = 0;
return Task.CompletedTask;
}
public Task<int> Get()
{
return Task.FromResult(this.State);
}
// Delete is implicitly defined when defining an entity this way
[Function(nameof(Counter))]
public static Task Run([EntityTrigger] TaskEntityDispatcher dispatcher)
=> dispatcher.DispatchAsync<Counter>();
}
}
FunctionApp9.csproj
:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.1.2" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.2" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
</ItemGroup>
</Project>
OUTPUT
: