{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/corefx/issues/3480","labels_url":"https://api.github.com/repos/dotnet/corefx/issues/3480/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/corefx/issues/3480/comments","events_url":"https://api.github.com/repos/dotnet/corefx/issues/3480/events","html_url":"https://github.com/dotnet/corefx/issues/3480","id":108466052,"number":3480,"title":"Make interfaces as the official ADO.NET Provider API instead of classes","user":{"login":"nvivo","id":202449,"avatar_url":"https://avatars.githubusercontent.com/u/202449?v=3","gravatar_id":"","url":"https://api.github.com/users/nvivo","html_url":"https://github.com/nvivo","followers_url":"https://api.github.com/users/nvivo/followers","following_url":"https://api.github.com/users/nvivo/following{/other_user}","gists_url":"https://api.github.com/users/nvivo/gists{/gist_id}","starred_url":"https://api.github.com/users/nvivo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nvivo/subscriptions","organizations_url":"https://api.github.com/users/nvivo/orgs","repos_url":"https://api.github.com/users/nvivo/repos","events_url":"https://api.github.com/users/nvivo/events{/privacy}","received_events_url":"https://api.github.com/users/nvivo/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/corefx/labels/System.Data","name":"System.Data","color":"d4c5f9"}],"state":"open","locked":false,"assignee":{"login":"YoungGah","id":12972170,"avatar_url":"https://avatars.githubusercontent.com/u/12972170?v=3","gravatar_id":"","url":"https://api.github.com/users/YoungGah","html_url":"https://github.com/YoungGah","followers_url":"https://api.github.com/users/YoungGah/followers","following_url":"https://api.github.com/users/YoungGah/following{/other_user}","gists_url":"https://api.github.com/users/YoungGah/gists{/gist_id}","starred_url":"https://api.github.com/users/YoungGah/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/YoungGah/subscriptions","organizations_url":"https://api.github.com/users/YoungGah/orgs","repos_url":"https://api.github.com/users/YoungGah/repos","events_url":"https://api.github.com/users/YoungGah/events{/privacy}","received_events_url":"https://api.github.com/users/YoungGah/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/dotnet/corefx/milestones/4","html_url":"https://github.com/dotnet/corefx/milestones/1.0.0-rtm","labels_url":"https://api.github.com/repos/dotnet/corefx/milestones/4/labels","id":1248719,"number":4,"title":"1.0.0-rtm","description":"Q1 2016 (https://github.com/aspnet/Home/wiki/Roadmap)","creator":{"login":"joshfree","id":1302850,"avatar_url":"https://avatars.githubusercontent.com/u/1302850?v=3","gravatar_id":"","url":"https://api.github.com/users/joshfree","html_url":"https://github.com/joshfree","followers_url":"https://api.github.com/users/joshfree/followers","following_url":"https://api.github.com/users/joshfree/following{/other_user}","gists_url":"https://api.github.com/users/joshfree/gists{/gist_id}","starred_url":"https://api.github.com/users/joshfree/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joshfree/subscriptions","organizations_url":"https://api.github.com/users/joshfree/orgs","repos_url":"https://api.github.com/users/joshfree/repos","events_url":"https://api.github.com/users/joshfree/events{/privacy}","received_events_url":"https://api.github.com/users/joshfree/received_events","type":"User","site_admin":false},"open_issues":221,"closed_issues":103,"state":"open","created_at":"2015-08-10T18:04:00Z","updated_at":"2015-11-27T20:49:45Z","due_on":"2016-03-31T07:00:00Z","closed_at":null},"comments":103,"created_at":"2015-09-26T13:50:32Z","updated_at":"2015-11-28T13:07:11Z","closed_at":null,"body":"From what I can see currently on the [corefx-progress page for System.Data.Common](https://github.com/dotnet/corefx-progress/blob/master/src-diff/System.Data.Common.md), the interfaces (IDbCommand, IDbConnection, etc) were removed in favor of the usage of abstract classes.\r\n\r\nBut in the new API, most of the main methods are not virtual or abstract. On DbCommand alone we can see this:\r\n\r\n```cs\r\npublic DbConnection Connection { get; set; }\r\npublic DbParameterCollection Parameters { get; }\r\npublic DbTransaction Transaction { get; set; }\r\npublic DbParameter CreateParameter();\r\npublic Task<int> ExecuteNonQueryAsync();\r\npublic DbDataReader ExecuteReader();\r\npublic DbDataReader ExecuteReader(CommandBehavior behavior);\r\npublic Task<DbDataReader> ExecuteReaderAsync();\r\npublic Task<DbDataReader> ExecuteReaderAsync(CommandBehavior behavior);\r\npublic Task<DbDataReader> ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken);\r\npublic Task<DbDataReader> ExecuteReaderAsync(CancellationToken cancellationToken);\r\npublic Task<object> ExecuteScalarAsync();\r\n```\r\n\r\nWhile these methods can certainly be made virtual or abstract, it would be much more useful to have the real interfaces back, and make any public API depend on these interfaces instead of the abstract classes. \r\n\r\nThis is mostly useful when developing libraries. Today it's very hard to mock a datareader to make it return a specific value for testing purposes. The same for ensuring that ExecuteReaderAsync was called, not ExecuteReader, etc.\r\n\r\nI propose the provider factory instead should be made as an interface:\r\n\r\n```cs\r\npublic interface IDbProviderFactory {\r\n\tIDbCommand CreateCommand();\r\n\tIDbConnection CreateConnection();\r\n\tIDbConnectionStringBuilder CreateConnectionStringBuilder();\r\n\tIDbParameter CreateParameter();\r\n}\r\n```\r\n\r\nAnd then follow from there to the rest of the provider to things like `IDbDataReader`, `IDbTransaction`, etc.\r\n\r\nWe know the interfaces became out of sync for some reason in the past and the abstract classes were made the official API, but this doesn't need to be the case anymore in corefx.\r\n\r\nNote that this doesn't mean removing the System.Data.Common in any way, but instead make the Common classes implement these interfaces, and you wouldn't use System.Data.Common unless you're implementing the provider. Applications would depend only on the interfaces instead.\r\n\r\nPlease consider this to make the API more testable on corefx 1.0.\r\n\r\nRelated to discussions on #1039 and #3423."},"comment":{"url":"https://api.github.com/repos/dotnet/corefx/issues/comments/160294658","html_url":"https://github.com/dotnet/corefx/issues/3480#issuecomment-160294658","issue_url":"https://api.github.com/repos/dotnet/corefx/issues/3480","id":160294658,"user":{"login":"nvivo","id":202449,"avatar_url":"https://avatars.githubusercontent.com/u/202449?v=3","gravatar_id":"","url":"https://api.github.com/users/nvivo","html_url":"https://github.com/nvivo","followers_url":"https://api.github.com/users/nvivo/followers","following_url":"https://api.github.com/users/nvivo/following{/other_user}","gists_url":"https://api.github.com/users/nvivo/gists{/gist_id}","starred_url":"https://api.github.com/users/nvivo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nvivo/subscriptions","organizations_url":"https://api.github.com/users/nvivo/orgs","repos_url":"https://api.github.com/users/nvivo/repos","events_url":"https://api.github.com/users/nvivo/events{/privacy}","received_events_url":"https://api.github.com/users/nvivo/received_events","type":"User","site_admin":false},"created_at":"2015-11-28T13:07:11Z","updated_at":"2015-11-28T13:07:11Z","body":"> I'd much rather see an IDbAsyncConnection added when a provider supports it rather than a bunch of methods that are synchronous under the covers leading to confusion and inefficiency\r\n\r\n@NickCraver +1000 to that. Like this bug [here](https://bugs.mysql.com/bug.php?id=70111) where the oracle team just doesn't understand what async means."}}