Description
Some ADO.NET APIs create objects which not all providers support. For example, DbProviderFactory.CreateCommandBuilder()
returns a DbCommandBuilder
, but some providers don't support this functionality (e.g. SQLite if I'm not mistaken, @bricelam). The current implementation for all the methods on DbProviderFactory is to return null by default, which serves as a sort of "feature detection mechanism" - consumers can check if the result is null to know if the feature is supported or not.
Aside being a generally problematic mechanism (users get NullReferenceException instead of the clearer NotSupportedException), this mechanism is also not suited for C# 8 nullability. If certain providers can return null to indicate that the feature isn't supported, than it seems like the Create*()
method will return a nullable reference. This would impose on everyone to either check for null, or use the bang (!) operator to tell the compiler that no null is actually possible there - not good practice since users simply know that their specific provider supports the feature. Conversely, if the Create*()
method returns a non-nullable reference, then you may get warnings for checking it for null.
Instead, we should change these methods to throw NotSupportedException (breaking change), and add Can*()
virtual bool properties alongside these methods to indicate whether the feature is supported or not (similar to how DbProviderFactory.CanCreateDataSourceEnumerator
exists alongside DbProviderFactory.CreateDataSourceEnumerator()
. The default implementation of these capability properties could be to call the corresponding method, catching NotSupportedException and returning based on that.
This should be done for .NET Standard 2.1 if possible.
Originally discussed in https://github.com/dotnet/corefx/issues/35135#issuecomment-466452344