14

I'm facing really strange issue. Given the code below:

static void Main()
{
    var c = new System.Data.SqlClient.SqlConnection();

    c.ConnectionString = "Data Source=SOME_NAME;Initial Catalog=SOME_DB;Integrated Security=True";
    c.ConnectionString = ""; //null also triggers exception

    Console.WriteLine("Success");
}

It worked fine for quite a time, but on newest version of Windows 10 (1803) which has .NET Version 4.7.03056 Release 461808 (seems to be 4.7.2) it crashes with following exception:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Data.SqlClient.SqlConnection.CacheConnectionStringProperties()
   at System.Data.SqlClient.SqlConnection.set_ConnectionString(String value)
   at TestCacheConnectionStringProperties.Program.Main()

This crashes on the second assignment, if I remove any of the assignments of the ConnectionString it works ok.

I've looked at the sources and didn't find a place where NullReferenceException could happen (however sources seems to be for .NET Framework 4.7.1 so smth may change).

Now the question is - what causes this issue? Is this a .NET bug? If yes - how to address it?

UPDATE: According to the comments - thanks very much guys - the issue is caused by these lines (decompiled):

private void CacheConnectionStringProperties()
{
  SqlConnectionString connectionOptions = this.ConnectionOptions as SqlConnectionString;
  if (connectionOptions != null)
    this._connectRetryCount = connectionOptions.ConnectRetryCount;

  //Seems like this is causing the bug because it is not inside of null-check-if for connectionOptions variable
  if (this._connectRetryCount != 1 || !ADP.IsAzureSqlServerEndpoint(connectionOptions.DataSource))
    return;
  this._connectRetryCount = 2;
}

It is somehow related to Azure and is quite different from what is available in sources.

I've posted the issue here and will wait for response.

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
Pavel K
  • 3,541
  • 2
  • 29
  • 44
  • I don't really think that .net version has anything to do with it...But just for your satisfaction,you can try switching back to 4.7.1 and see if anything changes :) – Software Dev May 04 '18 at 14:53
  • 3
    This is a bug in (some version of) `CacheConnectionStringProperties`. My IL decompiler for assembly version `4.7.3056.0` shows a call to `ADP.IsAzureSqlServerEndpoint(sqlConnectionString.DataSource)` that is, improperly, outside the check for whether `sqlConnectionString` is `null`. It's not [here](https://github.com/dotnet/corefx/blob/master/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlConnection.cs/#L104), though, so I'm not sure where those bits are coming from. – Jeroen Mostert May 04 '18 at 15:16
  • For me, the bug only appears if you set `ConnectionString` to an empty value after having set it to something that isn't empty. In that sense, the workaround is simple: don't do that, then. Changing the `ConnectionString` value after construction is a peculiar thing to do which ought to be avoidable in your code. Alternatively, change the connection string to something non-empty but unconnectable (`Application Name=`) and check for that, if it's something you check for. – Jeroen Mostert May 04 '18 at 15:19
  • 6
    I don't like that questions are not even being read before marked as a duplicate – adjan May 04 '18 at 15:20
  • 1
    I've adjusted the title to make it clear that it is .NET code which causes the error, not mine. Please reopen this, it is not a duplicate – Pavel K May 04 '18 at 15:32
  • @PavelK It was just reopened :) – adjan May 04 '18 at 15:33
  • @Adrian fortunately this happens mostly in this specific case, when NullReferenceException is mentioned, not in general. – Evk May 04 '18 at 15:33
  • @PavelK if this exception is thrown in third party code - this is always a bug and reasonable thing to do is to report it to related bug tracker. – Evk May 04 '18 at 15:35
  • @PavelK SqlClient is available as a NuGet package. You should probably use the NuGet package – Panagiotis Kanavos May 04 '18 at 15:36
  • 1
    @Evk hard to do when you can't find the relevant bug tracker. Perhaps we should use the `Twitter` bug tracker – Panagiotis Kanavos May 04 '18 at 15:44
  • @JeroenMostert what does the call stack look like? There's no call to IsAzureSqlServerEndpoint in the entire corefx repo. Useful to know who needs (n|t)agging in the Twitter bug tracker – Panagiotis Kanavos May 04 '18 at 15:46
  • @PanagiotisKanavos: The call stack is as the OP posted and is the same as in corefx -- the `SqlConnectionString.ConnectionString` setter calls `CacheConnectionStringProperties` at the end. If you mean the method contents, the relevant difference is the inclusion of an extra block: `if (this._connectRetryCount == 1 && ADP.IsAzureSqlServerEndpoint(sqlConnectionString.DataSource)) { this._connectRetryCount = 2; }`. (`sqlConnectionString` is actually named `connStr` in the original source.) At this point, `connStr` is `null` (verified by getting `ConnectionOptions` through reflection.) – Jeroen Mostert May 04 '18 at 15:51
  • @JeroenMostert I mean "what do I post when I start nagging". NuGet packages seem to work OK, even the latest. The repos don't contain anything like that. Trying to extract the offline installer files now ... – Panagiotis Kanavos May 04 '18 at 16:00
  • The release version for this one is 461808, which is (according to [this](https://learn.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed)) .NET 4.7.2 on the Windows 10 April 2018 update (and only that). Let's hope we don't have a rogue builder on our hands. :-) Note that I'm not actually 100% sure I had .NET 4.7.2 before the WIndows update itself; that may or may not be relevant. – Jeroen Mostert May 04 '18 at 16:00
  • @JeroenMostert if only :(. Found it in the offline installer, in the `system_data_dll_gac_amd64` file. Sometimes, it *is* zebras. Let's hope they don't try some `this is a feature` stunt, after all there's a null check there – Panagiotis Kanavos May 04 '18 at 16:06
  • 3
    @PanagiotisKanavos: I'm sure it's a feature that'll improve things for Azure, and it may even be a very nice feature once it works 100%, but it's more worrisome that the binary bits for this version don't appear to have any publicly available source somewhere. Either someone's private branch ended up in the build or there's still steps for building the framework bits for release that aren't documented anywhere. Neither possibility is attractive, but as long as it's a mistake and not a structural flaw it's OK. – Jeroen Mostert May 04 '18 at 16:15
  • @JeroenMostert never say no to a chance for a good-natured nag – Panagiotis Kanavos May 04 '18 at 16:17
  • 1
    For everyone coming to this after the nags, decompilation shows `if (this._connectRetryCount == 1 && ADP.IsAzureSqlServerEndpoint(connectionOptions.DataSource)) { this._connectRetryCount = 2; }` *after* the null-check block. If `connectionOptions` is null, an NRE is thrown. – Panagiotis Kanavos May 04 '18 at 16:20
  • 1
    Reported an issue [here](https://developercommunity.visualstudio.com/content/problem/246156/nullreferenceexception-inside-net-code-of-sqlconne.html) – Pavel K May 07 '18 at 07:31

1 Answers1

2

This is a documented known issue in System.Data in .NET Framework 4.7.2 https://github.com/Microsoft/dotnet/blob/master/releases/net472/dotnet472-known-issues.md

The issue is currently being addressed and will be available in future updates of .NET Framework 4.7.2