<p><strong>SOLVED</strong>: This error came from a table being locked through the open transaction and the other function call tried to wait for the unlock until it timed out.</p>
<p>I'm currently working on an Azure Function app in .NET Core and trying to add transactions for requests. The problem is, when a function call is doing work between a <code>context.Database.BeginTransaction(...)</code> call and a <code>transaction.CommitAsync(...)</code> call, then another function call can not save to the database and gets a timeout:</p>
<pre><code>[2024-01-04T07:23:29.957Z] An exception occurred in the database while saving changes for context type 'MyContext'.
[2024-01-04T07:23:29.957Z] System.InvalidOperationException: An exception has been raised that is likely due to a transient failure.
[2024-01-04T07:23:29.957Z] ---> Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
[2024-01-04T07:23:29.958Z] ---> Npgsql.NpgsqlException (0x80004005): Exception while reading from stream
[2024-01-04T07:23:29.958Z] ---> System.TimeoutException: Timeout during reading attempt
</code></pre>
<p>This other function call can save perfectly fine, when the "long running" function call is not being called beforehand. So I suppose the open transaction is blocking the <code>DbContext</code> in other function calls.</p>
<p>Our <code>DbContext</code> gets registered like this:</p>
<pre class="lang-cs prettyprint-override"><code>builder.Services.AddDbContext<MyContext>(
options => options
.UseNpgsql(dbConnStr)
.UseSnakeCaseNamingConvention());
</code></pre>
<p>From what I understand each function call should get its own dependency injection scope, just like in ASP .NET Core, where the "same" setup works without any problems.</p>
<p>Am I missing something?</p>
<p><strong>EDIT:</strong> I've found someone with the same problem buried in an old Github issue: <a href="https://github.com/Azure/azure-functions-host/issues/5098#issuecomment-896712016" rel="nofollow noreferrer">https://github.com/Azure/azure-functions-host/issues/5098#issuecomment-896712016</a> but there doesn't seem to be a followup with a solution.</p>
<p><strong>EDIT 2:</strong></p>
<p>Basic outline of the 2 functions (<code>_dbContext</code> gets injected with ctor):</p>
<pre class="lang-cs prettyprint-override"><code>public class LongerRunningFunctionClass {
[Function("LongerRunningFunction"😉]
public HttpResponseData LongerRunningFunction([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post"😉] HttpRequestData req, FunctionContext executionContext) {
await using var transaction = await _dbContext.Database.BeginTransactionAsync();
try {
// Imagine some code here inserting data into the database
// and doing calls to external services
await transaction.CommitAsync();
}
catch (Exception) {
await transaction.RollbackAsync();
throw;
}
}
}
public class OtherFunctionClass {
[Function("OtherFunction"😉]
public HttpResponseData OtherFunction([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post"😉] HttpRequestData req, FunctionContext executionContext) {
await using var transaction = await _dbContext.Database.BeginTransactionAsync();
try {
// Imagine a quick insert here
await transaction.CommitAsync();
}
catch (Exception) { // <-- I fall into this catch when the other function is still executing with above error
await transaction.RollbackAsync();
throw;
}
}
}
</code></pre>