1

I am developping an API that will be the link between my website and the database. For developement purposes (won't be available in production), I am creating a database controller that I can use to drop and recreate my database.

This is the problematic code, that I took here :

public async void CreateDatabaseAndTables()
{
    // When not specifying a migration name in MigrateAsync, the method calls the last migration executed
    await this._instituteDbContext.GetInfrastructure().GetService<IMigrator>().MigrateAsync();
}

When I first executed it, I had a TaskCancelledException. After investigating, I found this. I then checked my exception and from there I was able to find out that the task is cancelled (probably) due to a timeout.

Following this post, I tried to set a new timeout :

builder.WebHost.UseKestrel(options =>
{
    options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(60);
});

But it didn't fix my issue.

So I am wondering if there is another solution to this or if I have to investigate somewhere else to find the cause of the issue, if it's not due to a timeout exceeded ?

Unhandled exception. System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.<>c__DisplayClass20_0.<<ExistsAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.<>c__DisplayClass20_0.<<ExistsAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func 4 operation, Func 4 verifySucceeded, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.ExistsAsync(CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.GetAppliedMigrationsAsync(CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.GetAppliedMigrationsAsync(DatabaseFacade databaseFacade, CancellationToken cancellationToken)
   at Infrastructure.SqlServer.System.DatabaseManager.CreateDatabaseAndTables() in D:\Progra\CSharp\Privé\InstitutServeur\Infrastructure\SqlServer\System\DatabaseManager.cs:line 32
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
   at System.Threading.QueueUserWorkItemCallback.<>c.<.cctor>b__6_0(QueueUserWorkItemCallback quwi)
   at System.Threading.ExecutionContext.RunForThreadPoolUnsafe[TState](ExecutionContext executionContext, Action`1 callback, TState& state)
   at System.Threading.QueueUserWorkItemCallback.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
   at System.Threading.Thread.StartCallback()

EDIT : I tried to fix the issue by changing my mistake (writing "void" instead of "Task"). But I still have the same issue, and even further investigation didn't help me.

I wrote this in the method (which goal is to drop and recreate the database), but it gives the same exception of cancelled Task :

await this._instituteDbContext.Database.EnsureDeletedAsync();
await this._instituteDbContext.Database.EnsureCreatedAsync();
await this._instituteDbContext.Database.MigrateAsync();

I can't find why does my app cancels this Task, and I have, atm, no more info to give about the exception.

Scryper
  • 178
  • 1
  • 14

1 Answers1

1

Kestrel timeout has nothing to do with the timeout for EF Core database calls. You can change that either during the context registration:

services.AddDbContext<SomeContext>(builder => 
    builder.UseSqlite($"Filename={nameof(SomeContext)}.db", opts => opts.CommandTimeout(3600))); 

Or for concrete context instance:

ctx.Database.SetCommandTimeout(3600); // possibly will require restoration in some cases

Still I would recommend investigating what is causing the timeout - EF Core allows to generate migration SQL script and you can use it to either apply migration manually or see what is wrong.

Also you should avoid async void methods, change CreateDatabaseAndTables signature to:

public async Task CreateDatabaseAndTables()
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • I will continue investigating on this, none of the options you presented worked, the task still get cancelled. I will update you if I find something. – Scryper Sep 04 '22 at 22:59
  • 4
    @Scryper you might want to change `public async void CreateDatabaseAndTables()` to `public async Task CreateDatabaseAndTables()` also. – Guru Stron Sep 04 '22 at 23:09
  • I answered too fast, I still get the task cancelled. At first I thought it was fixed, but then when trying to reset my db, I saw that it had no effect. I then reran the project in debug mode, and saw I was still getting the same exception. – Scryper Sep 13 '22 at 19:02