In my .NET 8 app, migrating my contexts takes 10 seconds on my machine. And since I run hundreds of independent xUnit tests that each have their own databases, the complete suite of tests ends up being too slow, even with parallelism.
I wonder what EF Core does so I can cache it as it's a common step to all my tests.
Any ideas? Maybe a pool of databases that the tests could pick, clear and reuse in parallel?
I ended up having a finite stack of unique database names. I pop a new name when needed and at the end of each test I clear the database to then recycle the database name by pushing it back to the stack.
public class WebApplicationFactoryHelper
{
private static readonly ConcurrentStack<Guid> Suffixes = new([
Guid.Parse("7a00615f-c58a-4d4f-a0b7-081a881f58ac"),
Guid.Parse("2ff693ef-e0ba-4430-bfc1-ac1a9288c99b"),
Guid.Parse("23ec38d9-7b9c-46b5-9fcb-861f76dd500b"),
Guid.Parse("7cd51fb0-3a8e-4828-bab1-9d87c2703f1a"),
...
]);
public static async Task RecycleDb(Guid suffix)
{
var connectionString = $"Server=localhost;Database={suffix};Trusted_Connection=True;TrustServerCertificate=Yes;MultipleActiveResultSets=true";
const string sql = """
EXEC sp_MSForEachTable
@command1 = '
SET QUOTED_IDENTIFIER ON;
IF ''?'' <> ''[dbo].[__EFMigrationsHistory]''
BEGIN
IF ''?'' = ''[dbo].[AspNetUsers]''
BEGIN
DELETE FROM dbo.AspNetUsers WHERE UserName <> ''SpecificSeededUserName''
END
ELSE
BEGIN
DELETE FROM ?
END
END'
""";
await using var connection = new SqlConnection(connectionString);
await connection.ExecuteAsync(sql);
Suffixes.Push(suffix);
}
public static Guid ConfigureDbSync(IServiceCollection serviceCollection)
{
var suffix = Suffixes.TryPop(out var result) ? result : throw new Exception("not enough dbs");
var connectionString = $"Server=localhost;Database={suffix};Trusted_Connection=True;TrustServerCertificate=Yes;MultipleActiveResultSets=true";
serviceCollection.Replace(new ServiceDescriptor(typeof(SqlConnection), _ => new SqlConnection(connectionString), ServiceLifetime.Scoped));
return suffix;
}
}