-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: System.Data.IAsyncDbConnection #81723
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
And, since it is supposed to change interfaces, why are the |
Tagging subscribers to this area: @roji, @ajcvickers Issue DetailsBackground and motivation
API ProposalFrom IDbConnection we select the common: public interface IDbConnectionCommon
{
//
// Summary:
// Gets or sets the string used to open a database.
//
// Returns:
// A string containing connection settings.
string ConnectionString { get; set; }
//
// Summary:
// Gets the time to wait (in seconds) while trying to establish a connection before
// terminating the attempt and generating an error.
//
// Returns:
// The time (in seconds) to wait for a connection to open. The default value is
// 15 seconds.
int ConnectionTimeout { get; }
//
// Summary:
// Gets the name of the current database or the database to be used after a connection
// is opened.
//
// Returns:
// The name of the current database or the name of the database to be used once
// a connection is open. The default value is an empty string.
string Database { get; }
//
// Summary:
// Gets the current state of the connection.
//
// Returns:
// One of the System.Data.ConnectionState values.
ConnectionState State { get; }
} The IDbConnection interface then inherits from IDbConnectionCommon: //
// Summary:
// Represents an open connection to a data source, and is implemented by .NET Framework
// data providers that access relational databases.
public interface IDbConnection : IDbConnectionCommon, IDisposable
{
//
// Summary:
// Begins a database transaction.
//
// Returns:
// An object representing the new transaction.
IDbTransaction BeginTransaction();
//
// Summary:
// Begins a database transaction with the specified System.Data.IsolationLevel value.
//
// Parameters:
// il:
// One of the System.Data.IsolationLevel values.
//
// Returns:
// An object representing the new transaction.
IDbTransaction BeginTransaction(IsolationLevel il);
//
// Summary:
// Changes the current database for an open Connection object.
//
// Parameters:
// databaseName:
// The name of the database to use in place of the current database.
void ChangeDatabase(string databaseName);
//
// Summary:
// Closes the connection to the database.
void Close();
//
// Summary:
// Creates and returns a Command object associated with the connection.
//
// Returns:
// A Command object associated with the connection.
IDbCommand CreateCommand();
//
// Summary:
// Opens a database connection with the settings specified by the ConnectionString
// property of the provider-specific Connection object.
void Open();
} The IAsyncDbConnection interface will be like this: public interface IAsyncDbConnection : IDbConnectionCommon, IAsyncDisposable
{
//
// Summary:
// Asynchronously begins a database transaction.
//
// Parameters:
// cancellationToken:
// An optional token to cancel the asynchronous operation. The default value is
// System.Threading.CancellationToken.None.
//
// Returns:
// A task whose System.Threading.Tasks.Task`1.Result property is an object representing
// the new transaction.
ValueTask<DbTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default);
//
// Summary:
// Asynchronously begins a database transaction.
//
// Parameters:
// isolationLevel:
// One of the enumeration values that specifies the isolation level for the transaction
// to use.
//
// cancellationToken:
// An optional token to cancel the asynchronous operation. The default value is
// System.Threading.CancellationToken.None.
//
// Returns:
// A task whose System.Threading.Tasks.Task`1.Result property is an object representing
// the new transaction.
ValueTask<DbTransaction> BeginTransactionAsync(IsolationLevel isolationLevel, CancellationToken cancellationToken = default);
//
// Summary:
// Asynchronously changes the current database for an open connection.
//
// Parameters:
// databaseName:
// The name of the database for the connection to use.
//
// cancellationToken:
// An optional token to cancel the asynchronous operation. The default value is
// System.Threading.CancellationToken.None.
//
// Returns:
// A task representing the asynchronous operation.
Task ChangeDatabaseAsync(string databaseName, CancellationToken cancellationToken = default);
//
// Summary:
// Asynchronously closes the connection to the database.
//
// Returns:
// A System.Threading.Tasks.Task representing the asynchronous operation.
Task CloseAsync();
//
// Summary:
// An asynchronous version of System.Data.Common.DbConnection.Open, which opens
// a database connection with the settings specified by the System.Data.Common.DbConnection.ConnectionString.
// This method invokes the virtual method System.Data.Common.DbConnection.OpenAsync(System.Threading.CancellationToken)
// with CancellationToken.None.
//
// Returns:
// A task representing the asynchronous operation.
Task OpenAsync();
//
// Summary:
// This is the asynchronous version of System.Data.Common.DbConnection.Open. Providers
// should override with an appropriate implementation. The cancellation token can
// optionally be honored. The default implementation invokes the synchronous System.Data.Common.DbConnection.Open
// call and returns a completed task. The default implementation will return a cancelled
// task if passed an already cancelled cancellationToken. Exceptions thrown by Open
// will be communicated via the returned Task Exception property. Do not invoke
// other methods and properties of the DbConnection object until the returned Task
// is complete.
//
// Parameters:
// cancellationToken:
// The cancellation instruction.
//
// Returns:
// A task representing the asynchronous operation.
Task OpenAsync(CancellationToken cancellationToken);
} Then the DbConnection inheritance will be like this:: public abstract class DbConnection : Component, IDbConnection, IDisposable, IAsyncDbConnection, IAsyncDisposable API Usage public async void SomeMethod(IAsyncDbConnection dbConnection)
{
await dbConnection.OpenAsync();
await using (dbConnection)
{
await using (var transaction = await dbConnection.BeginTransactionAsync())
{
//do something
}
}
} Alternative DesignsDo not allocate the common RisksNo response
|
@SoftStoneDevelop we do not intend to evolve System.Data interfaces by adding additional ones for async support. For one thing, other non-async APIs have been added that would require yet other interfaces, causing an interface explosion. C# now supports default interface implementations, which in theory could allow us to add the missing methods directly into e.g. IDbConnection without causing a breaking change. However, the System.Data interfaces have been more or less obsolete for a very long time, precisely because they could not be evolved; instead, users use the abstract base classes (DbConnection instead of IDbConnection). Is there any specific reason you're not simply using those? |
@roji Because now I pass if(connection is DbConnection dbConnection)
{
//...
} if the method is asynchronous. Do all providers written for various .Net relational databases inherit from |
That's not really how it works; marking an API as obsolete is quite an extreme thing, which causes compilation warnings in applications using them (and errors where warnings-as-errors is enabled). IDbConnection isn't obsolete - it simply isn't being evolved.
Yes. The recommendation is simply to use the abstract base classes instead of the interfaces. |
In this case, I have no questions - I will use an abstract class. |
Background and motivation
System.Data.Common.DbConnection
already contains methods such asBeginTransactionAsync
,CloseAsync
and other asynchronous versions of theSystem.Data.IDbConnection
interface. It would be convenient to inheritDbConnection
fromSystem.Data.IAsyncDbConnection
.API Proposal
From IDbConnection we select the common:
The IDbConnection interface then inherits from IDbConnectionCommon:
The IAsyncDbConnection interface will be like this:
Then the DbConnection inheritance will be like this::
API Usage
Alternative Designs
Do not allocate the common
IDbConnectionCommon
interface, but duplicate its elements inIAsyncDbConnection
. This way theIDbConnection
will not be changed.Risks
No response
The text was updated successfully, but these errors were encountered: