It's great that System.Data.Common includes interfaces for the most implementations - it's easy to mock with and thus unit test our reader and parameter building routines. However, moving to async causes a problem since those implementations on DbCommand are not exposed via the interface.
DbCommand.ExecuteReaderAsync() does not have a matching IDbCommand.ExecuteReaderAsync() definition. Similarly for all the other execute methods.
Is there some design consideration that is preventing these definitions from being added? Or simply an oversight from the carry-over from the old framework code?
We can't simply add new members to an existing publicly exposed interface as that would break consumers. We could of course add an additional interface for the async methods but that is a decision that should be made by the area owners.
Is there some design consideration that is preventing these definitions from being added? Or simply an oversight from the carry-over from the old framework code?
We carry the existing interfaces for compatibility with existing code. As @ViktorHofer said, extending interfaces is a breaking change for implementers.
The base clases are the preferred way to address the APIs in a provider-agnostic way, are generally appropriate to create test doubles, and allow as to introduce new members (with default implementations) without needing to define new types.
There have been long discussions about whether interfaces have some inherent superiority here. They certainly have some nice characteristics (they carry zero policy) but are not ideal for the reasons previously mentioned.
There is a new language feature possibly coming in the future that could allow adding new members with default implementations to existing interfaces. We can revisit this decision in that context.
Additional note on new members with default implementations: these interfaces are now standardized across multiple .NET implementations. We would need to make sure adding members plays well with that.
System.Data and many applications built on System.Data assume that the interfaces can be cast to the base types. This greatly reduces the usefulness of the interfaces since in many cases different implementations than expected with result in exceptions. This means that, even with default interface implementations now available, we still don't plan to evolve these interfaces.
Most helpful comment
We carry the existing interfaces for compatibility with existing code. As @ViktorHofer said, extending interfaces is a breaking change for implementers.
The base clases are the preferred way to address the APIs in a provider-agnostic way, are generally appropriate to create test doubles, and allow as to introduce new members (with default implementations) without needing to define new types.
There have been long discussions about whether interfaces have some inherent superiority here. They certainly have some nice characteristics (they carry zero policy) but are not ideal for the reasons previously mentioned.
There is a new language feature possibly coming in the future that could allow adding new members with default implementations to existing interfaces. We can revisit this decision in that context.