-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Perf problem on existence checks caused by SqlClient's connection resiliency feature #7283
Comments
@Inspyro Is the sentence above a good summary of your request or are there other issues I missed? As mentioned at #6673 (comment) we have already discussed this issue and decided against trying to work around the new behavior of SqlClient. Creating a separate connection string for existence checks has been problematic in the past because there isn't a uniform way to create a new connection that will preserve credentials when you use SQL Server authentication: In .NET Framework I will try to do some basic testing to see if this approach works before we discuss this again in triage. I will also file a bug on SqlClient to get |
I did some more investigation and here is what I learned:
var connection = new SqlConnection(
@"Server=(localdb)\mssqllocaldb;Database=NewOne;Integrated Security=False;User id=diego;Password=&123Blah");
connection.Open();
connection.Close();
var connection2 = (SqlConnection)((ICloneable)connection).Clone();
connection2.ConnectionString += ";ConnectRetryCount=0";
connection2.Open(); Given all of this I re-discussed the issue with @ajcvickers who had done some investigation around it before and we both came to the conclusion that there isn't anything reasonable we can do on EF Core to address this problem in all cases. There is something we could do that would work in some cases though: Store aside the connection string passed to us in Note that this will fail if a We are now debating whether implementing this workaround in EF Core would actually be much better than making customers aware of the fact that SqlClient assumes In the end we suspect this whole issue could much better addressed if SqlClient exposed a way to temporarily override their connection resiliency feature. |
@divega Yes this sentence sums the issue up nicely In our case, we mainly are concerned with the performance of our unit tests, thus we had to edit all connection strings to disable connection resiliency. So for now docs are sufficient. However I would expect the .NET / EF Core Api to expose this setting to the user and probably disable resiliency by default for the "EnsureCreated / Deleted" methods, as it could easily lead to performance problems, that are hard to detect. So "temporarily overriding the connection resiliency feature" could be a nice fix, as you suggested. |
@divega Would it be an option to connect to master for the Exists check, instead of brute force opening an connection, then look in sys.databases?
See https://msdn.microsoft.com/en-us/library/ms178534.aspx?f=255&MSPPError=-2147217396 |
@ErikEJ we stopped doing that because it didn't always work, i.e. it requires you having access to master, which may not be the case for a couple of different reasons. For the scenarios in which it works it also requires manipulation of the connection to connect to master instead of the target database, which normally we would do in a separate connection object, so it posses the same challenges re obtaining an original connection string that is still complete and contains a password. |
Looks like Azure was the deciding factor in not making ConnectRetryCount default to 0 to prevent breaking changes :sad: |
@ErikEJ do you have some pointers to that? |
Yes this: https://blogs.msdn.microsoft.com/dotnet/2015/11/30/net-framework-4-6-1-is-now-available/ - but ConnectRetryCount was introduced before that, I realize now: https://msdn.microsoft.com/en-us/library/dn632678.aspx - and looking at the Word doc from the second link, it looks like "ConnectRetryCount=0" was considered the way of opting out. |
@Inspyro I have created https://github.com/dotnet/corefx/issues/14644 to cover what we believe is the best solution for this issue: have SqlClient expose a way to programmatically disable connection resiliency that we can leverage when checking for database existence. Feel free to up-vote it if you think it is a good idea. |
@divega sadly, that will not solve the issue for .net 4.5.1 to 4.6.x |
Bringing this back to triage since SqlClient now have a way for us to opt out--see dotnet/SqlClient#29 (comment) |
We now have the new SqlClient dependency, so this can now be implemented. #20805 |
With recent versions of SqlClient I'm seeing the old behavior again. I need to use |
Re-opened the SqlClient issue: dotnet/SqlClient#29 |
Tracking regression with #33399 |
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 and deletion (EnsureCreated/EnsureDeleted) 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 DB-Creation takes >10s (as this seems to be the default ConnectRetryInterval, even when the MSDN docs suggest something else).
Repro sample
I hope this helps you fix the API or adapt the docs.
But in my opinion the current API (EF Core) 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.
Note: This issue was ported from EF 6 (http://entityframework.codeplex.com/workitem/2899) and re-tested with the EF.Core 1.1.0 (nuget package)
The text was updated successfully, but these errors were encountered: