Skip to content

ADO.NET factory methods should throw instead of returning null #28768

Closed
@roji

Description

@roji

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions