With https://github.com/dotnet/corefx/issues/27445 allowing elimination of allocations in asynchronously-executing async methods, we should look into adding ValueTask-returning counterparts to ADO.NET. This would potentially allow zero-allocation database access.
Here are the current async methods:
Task DbConnection.OpenAsync(...);
Task<DbDataReader> DbCommand.ExecuteReaderAsync(...);
Task<DbDataReader> DbCommand.ExecuteDbDataReaderAsync(...);
Task<object> DbCommand.ExecuteScalarAsync(...);
Task DbCommand.ExecuteNonQueryAsync(...);
Task<bool> DbDataReader.ReadAsync(...);
Task<T> DbDataReader.GetFieldValueAsync<T>(...);
Task<bool> DbDataReader.IsDBNullAsync(...);
Notes:
-
Naming the new methods is going to be complicated. Some parts of corefx are lucky in that they're introducing ValueTask<T> overloads along with Span<T> (e.g. Stream), but ADO.NET has no such upcoming parameter changes/additions. Since there can't be yet another overload that only differs on the return type, and the "standard" name with just the Async suffix is taken, we need to come up with a new naming pattern.
-
There are some missing async methods in ADO.NET in general (e.g. DbCommand.Prepare(), DbConnection.BeginTransactionAsync(...), DbTransaction.CommitAsync(...)...). These can be added directly with return value ValueTask<T> (covered by issue https://github.com/dotnet/corefx/issues/35012). Naming of these new methods should probably be decided in the context of whatever new naming pattern we use for the ValueTask<T> returning variants of the existing async methods.
-
Also note that async APIs that return Task or Task<bool> (such as ReadAsync() and IsDBNullAsync()) can be implemented to return cached Task<T> instances when they complete synchronously to gain efficiency instead of adopting ValueTask<TResult>. This mitigates the need for ValueTask<T> returning variants for most APIs. Also, in terms of allocations, the advantage of ValueTask<T> is much greater the more fine grained the async methods are.
-
Compatibility for providers: It seems desirable to offer a default implementation of the Task-based method that calls AsTask() on the ValueTask<TResult> instance returned by the new API, so that new providers don't need to implement the old Task<TResult> version of the API but instead only implement the more efficient ValueTask<TResult> version. It also seems good not to force existing providers to switch.
**Updated by @divega on 1/13/2019 to consolidate with https://github.com/dotnet/corefx/issues/15011.
With https://github.com/dotnet/corefx/issues/27445 allowing elimination of allocations in asynchronously-executing async methods, we should look into adding ValueTask-returning counterparts to ADO.NET. This would potentially allow zero-allocation database access.
Here are the current async methods:
Notes:
Naming the new methods is going to be complicated. Some parts of corefx are lucky in that they're introducing
ValueTask<T>overloads along withSpan<T>(e.g. Stream), but ADO.NET has no such upcoming parameter changes/additions. Since there can't be yet another overload that only differs on the return type, and the "standard" name with just theAsyncsuffix is taken, we need to come up with a new naming pattern.There are some missing async methods in ADO.NET in general (e.g.
DbCommand.Prepare(),DbConnection.BeginTransactionAsync(...),DbTransaction.CommitAsync(...)...). These can be added directly with return valueValueTask<T>(covered by issue https://github.com/dotnet/corefx/issues/35012). Naming of these new methods should probably be decided in the context of whatever new naming pattern we use for theValueTask<T>returning variants of the existing async methods.Also note that async APIs that return
TaskorTask<bool>(such asReadAsync()andIsDBNullAsync()) can be implemented to return cachedTask<T>instances when they complete synchronously to gain efficiency instead of adoptingValueTask<TResult>. This mitigates the need forValueTask<T>returning variants for most APIs. Also, in terms of allocations, the advantage ofValueTask<T>is much greater the more fine grained the async methods are.Compatibility for providers: It seems desirable to offer a default implementation of the Task-based method that calls
AsTask()on theValueTask<TResult>instance returned by the new API, so that new providers don't need to implement the oldTask<TResult>version of the API but instead only implement the more efficientValueTask<TResult>version. It also seems good not to force existing providers to switch.**Updated by @divega on 1/13/2019 to consolidate with https://github.com/dotnet/corefx/issues/15011.