tabs ↹ over ␣ ␣ ␣ spaces

by Jiří {x2} Činčura

Faster MS SQL database existence checking with Entity Framework Core and Entity Framework

3 Oct 2018 2 mins Azure SQL, Entity Framework Core, MS SQL Server, SqlClient

Bit out of frustration when demoing features newest versions of Entity Framework Core, I’ve found out a new feature of SqlClient (SqlConnection to be precise) that’s available since .NET 4.5.1 that might affect speed when working often without existing database.

What I’m talking about is Idle Connection Resiliency feature (oddly I’ve found only PHP version). For our discussion the important part is that SqlClient performs retry with a small delay when opening the connection fails. This is usually good. But there are at least two places, when using Entity Framework Core or Entity Framework, where this is not desired.

One is when executing Migrations and not having a database at all. The other is when using EnsureDeleted and EnsureCreated combination, like when executing (integration) tests. Luckily the solution is pretty easy. Simply add ConnectRetryCount=0 to the connection string and you’re good to go. This will turn off the Idle Connection Resiliency feature, thus it’s not without, maybe, undesired side-effect.

Let’s see this in action. Below is simple code that uses EnsureDeleted and EnsureCreated (the ElapsedRestart, as the name suggests, returns elapsed time and restarts the stopwatch).

using (var db = new MyContext())
{
	var sw = Stopwatch.StartNew();
	Console.WriteLine("Deleting");
	db.Database.EnsureDeleted();
	Console.WriteLine(sw.ElapsedRestart());
	Console.WriteLine("Creating");
	db.Database.EnsureCreated();
	Console.WriteLine(sw.ElapsedRestart());

	Console.WriteLine();

	Console.WriteLine("Deleting");
	db.Database.EnsureDeleted();
	Console.WriteLine(sw.ElapsedRestart());
	Console.WriteLine("Creating");
	db.Database.EnsureCreated();
	Console.WriteLine(sw.ElapsedRestart());
}

Without the ConnectRetryCount=0 we can roughly 10 seconds delay first during EnsureDeleted, because the database does not exist and then in second batch during EnsureCreated, for the same reason.

Deleting
00:00:11.3410613
Creating
00:00:00.4671336

Deleting
00:00:00.0261642
Creating
00:00:10.2167985

Adding the ConnectRetryCount=0 makes it flow without any delays.

Deleting
00:00:00.7322148
Creating
00:00:00.4016524

Deleting
00:00:00.0207446
Creating
00:00:00.1830252

At the moment this cannot be changed programmatically, thus there’s not much Entity Framework Core or Entity Framework can do. But it’s already tracked (CoreFX, EFCore, EF6), so there’s a hope.

Profile Picture Jiří Činčura is .NET, C# and Firebird expert. He focuses on data and business layers, language constructs, parallelism, databases and performance. For almost two decades he contributes to open-source, i.e. FirebirdClient. He works as a senior software engineer for Microsoft. Frequent speaker and blogger at www.tabsoverspaces.com.