This project is read-only.
5

Closed

EF 6 - Bug concerning new connection resiliency feature (.Net 4.5) - Performance Problem

description

When using the same DbContext class (e.g. DbContext itself) with different connection strings, the Connection Resiliency Feature of .Net 4.5 causes DB-creation to take a long time (due to the DB-Existency checks).

I made a small repro sample where you can see the different effects.
Basically when using 2 default connection strings (without modified connection resiliency settings) with the same DbContext class, the second DB-Creation takes >10s (as this seems to be the default ConnectRetryInterval, even when the MSDN docs suggest something else).

Repro sample
 static void Main (string[] args)
    {
      // Default resiliency settings (since .NET 4.5)
      var defaultConnectionString = "Data Source=localhost;Initial Catalog=EFIdleResiliencyBug1;Integrated Security=SSPI";

      // Retry Interval = 3s (instead of 10 which seems to be the default)
      var connectionStringThreeSeconds = "Data Source=localhost;Initial Catalog=EFIdleResiliencyBug2;Integrated Security=SSPI;ConnectRetryInterval=3";

      // Retry Count = 0 (instead of 1) => means Resiliency Feature is disabled.
      var connectionStringZeroRetry = "Data Source=localhost;Initial Catalog=EFIdleResiliencyBug3;Integrated Security=SSPI;ConnectRetryCount=0;";

      // Here we also create a default connection string but with a different db
      var defaultConnectionString2 = "Data Source=localhost;Initial Catalog=EFIdleResiliencyBug4;Integrated Security=SSPI";

      //The first DB that is dropped is seemingly stored statically in EF.
      Drop(defaultConnectionString);
      Drop(connectionStringZeroRetry);
      Drop (connectionStringThreeSeconds);
      Drop (defaultConnectionString2);

      //The stored dropped connection string can be recreated very fast.
      Create(defaultConnectionString);

      //All other connection strings (same DbContext class) try to connect to the DB.
      Create (connectionStringThreeSeconds); // BUG: Takes 3s
      Create(connectionStringZeroRetry); // Takes no time (connection resiliency disabled)
      Create (defaultConnectionString2); // BUG: Takes 10s (seems to be the default RetryInterval for some reason).

      // Note: When using a different derived class from DBContext for each connection string the bug does not exist.

      // Expected Behavior: Ignore connection resiliency for checking if the db exists. (It should not take 3s or even 10s).
      // This is especially a problem when executing integration / unit tests that drop the db at the beginning.
    }

    private static void Create (string connectionString)
    {
      Console.WriteLine ($"Creating {connectionString}");
        var sw = Stopwatch.StartNew();

      using (var dbContext = new DbContext (connectionString))
      {
        dbContext.Database.CreateIfNotExists();
        Console.WriteLine ("Creating DB took: " + sw.Elapsed);
      }
    }

    private static void Drop (string connectionString)
    {
      Console.WriteLine ($"Droping {connectionString}");
        var sw = Stopwatch.StartNew();

      using (var dbContext = new DbContext (connectionString))
      {
        sw = Stopwatch.StartNew();
        dbContext.Database.Delete();

        Console.WriteLine ("Deleting DB took: " + sw.Elapsed);
      }
    }
I hope this helps you fix the API or adapt the docs.

But in my opinion the current API (EF6) suggests that you can use the same class (DBContext) for multiple connection strings (ctor for this). However with .Net 4.5 that causes serious performance problems.
This is especially noticable in our unit / integration tests where we drop multiple DBs with the same DBContext class and recreate them later.
Closed Dec 5, 2016 at 11:35 PM by RoMiller
EF Team Triage: We are transitioning this project to GitHub (https://github.com/aspnet/EntityFramework6). As part of this transition we are bulk closing a large number of issues in order that our new issue tracker will accurately reflect the work that our team is planning to complete on the EF6.x code base.

Moving forwards, our team will be fixing bugs, implementing small improvements, and accepting community contributions to the EF6.x code base. Larger feature work and innovation will happen in the EF Core code base (https://github.com/aspnet/EntityFramework). Closing a feature request in the EF6.x project does not exclude us implementing the feature in EF Core. In fact, a number of popular feature requests for EF have already been implemented in EF Core (alternate keys, batching in SaveChanges, etc.).

This is a bulk message to indicate that this issue was closed and not ported to the new issue tracker. The reasons for not porting this particular issue to GitHub may include:
• It was a bug report that does not contain sufficient information for us to be able to reproduce it 
• It was a question, but sufficient time has passed that it's not clear that taking the time to answer it would provide value to the person who asked it 
• It is a feature request that we are realistically not going to implement on the EF6.x code base
Although this issue was not ported, you may still re-open it in the new issue tracker for our team to reconsider (https://github.com/aspnet/EntityFramework6/issues). We will no longer be monitoring this issue tracker for comments, so please do not reply here.

comments

MrDisaster44 wrote Dec 20, 2016 at 4:50 PM