Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/libraries/System.Data.Common/ref/System.Data.Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1933,6 +1933,9 @@ public virtual void EnlistTransaction(System.Transactions.Transaction? transacti
public virtual System.Data.DataTable GetSchema() { throw null; }
public virtual System.Data.DataTable GetSchema(string collectionName) { throw null; }
public virtual System.Data.DataTable GetSchema(string collectionName, string?[] restrictionValues) { throw null; }
public virtual System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(System.Threading.CancellationToken cancellationToken = default) { throw null; }
public virtual System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(string collectionName, System.Threading.CancellationToken cancellationToken = default) { throw null; }
public virtual System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(string collectionName, string?[] restrictionValues, System.Threading.CancellationToken cancellationToken = default) { throw null; }
protected virtual void OnStateChange(System.Data.StateChangeEventArgs stateChange) { }
public abstract void Open();
public System.Threading.Tasks.Task OpenAsync() { throw null; }
Expand Down Expand Up @@ -2111,6 +2114,8 @@ protected virtual void Dispose(bool disposing) { }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public virtual int GetProviderSpecificValues(object[] values) { throw null; }
public virtual System.Data.DataTable GetSchemaTable() { throw null; }
public virtual System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaTableAsync(System.Threading.CancellationToken cancellationToken = default) { throw null; }
public virtual System.Threading.Tasks.Task<System.Collections.ObjectModel.ReadOnlyCollection<System.Data.Common.DbColumn>> GetColumnSchemaAsync(System.Threading.CancellationToken cancellationToken = default) { throw null; }
public virtual System.IO.Stream GetStream(int ordinal) { throw null; }
public abstract string GetString(int ordinal);
public virtual System.IO.TextReader GetTextReader(int ordinal) { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,21 +143,166 @@ public virtual void EnlistTransaction(System.Transactions.Transaction? transacti

// these need to be here so that GetSchema is visible when programming to a dbConnection object.
// they are overridden by the real implementations in DbConnectionBase

/// <summary>
/// Returns schema information for the data source of this <see cref="DbConnection" />.
/// </summary>
/// <returns>A <see cref="DataTable" /> that contains schema information.</returns>
/// <remarks>
/// If the connection is associated with a transaction, executing <see cref="GetSchema()" /> calls may cause
/// some providers to throw an exception.
/// </remarks>
public virtual DataTable GetSchema()
{
throw ADP.NotSupported();
}

/// <summary>
/// Returns schema information for the data source of this <see cref="DbConnection" /> using the specified
/// string for the schema name.
/// </summary>
/// <param name="collectionName">Specifies the name of the schema to return.</param>
/// <returns>A <see cref="DataTable" /> that contains schema information.</returns>
/// <exception cref="ArgumentException">
/// <paramref name="collectionName" /> is specified as <see langword="null" />.
/// </exception>
/// <remarks>
/// If the connection is associated with a transaction, executing <see cref="GetSchema(string)" /> calls may cause
/// some providers to throw an exception.
/// </remarks>
public virtual DataTable GetSchema(string collectionName)
{
throw ADP.NotSupported();
}

/// <summary>
/// Returns schema information for the data source of this <see cref="DbConnection" /> using the specified
/// string for the schema name and the specified string array for the restriction values.
/// </summary>
/// <param name="collectionName">Specifies the name of the schema to return.</param>
/// <param name="restrictionValues">Specifies a set of restriction values for the requested schema.</param>
/// <returns>A <see cref="DataTable" /> that contains schema information.</returns>
/// <exception cref="ArgumentException">
/// <paramref name="collectionName" /> is specified as <see langword="null" />.
/// </exception>
/// <remarks>
/// <para>
/// The <paramref name="restrictionValues" /> parameter can supply n depth of values, which are specified by the
/// restrictions collection for a specific collection. In order to set values on a given restriction, and not
/// set the values of other restrictions, you need to set the preceding restrictions to null and then put the
/// appropriate value in for the restriction that you would like to specify a value for.
/// </para>
/// <para>
/// An example of this is the "Tables" collection. If the "Tables" collection has three restrictions (database,
/// owner, and table name) and you want to get back only the tables associated with the owner "Carl", you must
/// pass in the following values at least: null, "Carl". If a restriction value is not passed in, the default
/// values are used for that restriction. This is the same mapping as passing in null, which is different from
/// passing in an empty string for the parameter value. In that case, the empty string ("") is considered to be
/// the value for the specified parameter.
/// </para>
/// <para>
/// If the connection is associated with a transaction, executing <see cref="GetSchema(string, string[])" />
/// calls may cause some providers to throw an exception.
/// </para>
/// </remarks>
public virtual DataTable GetSchema(string collectionName, string?[] restrictionValues)
{
throw ADP.NotSupported();
}

/// <summary>
/// This is the asynchronous version of <see cref="GetSchema()" />.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this should be in remarks I think. The summary should be similar to the sync version.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Same for the others)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephentoub you're right, the docs for all async methods currently point to the sync method and add some notes on the default implementation - not ideal. I've opened #39154 to clean this up globally in System.Data, will take care of that after this PR.

/// Providers should override with an appropriate implementation.
/// The cancellation token can optionally be honored.
/// The default implementation invokes the synchronous <see cref="GetSchema()" /> call and returns a completed
/// task.
/// The default implementation will return a cancelled task if passed an already cancelled cancellationToken.
/// Exceptions thrown by <see cref="GetSchema()" /> will be communicated via the returned Task Exception
/// property.
/// </summary>
/// <param name="cancellationToken">The cancellation instruction.</param>
/// <returns>A task representing the asynchronous operation.</returns>
public virtual Task<DataTable> GetSchemaAsync(CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled<DataTable>(cancellationToken);
}

try
{
return Task.FromResult(GetSchema());
}
catch (Exception e)
{
return Task.FromException<DataTable>(e);
}
}

/// <summary>
/// This is the asynchronous version of <see cref="GetSchema(string)" />.
/// Providers should override with an appropriate implementation.
/// The cancellation token can optionally be honored.
/// The default implementation invokes the synchronous <see cref="GetSchema(string)" /> call and returns a
/// completed task.
/// The default implementation will return a cancelled task if passed an already cancelled cancellationToken.
/// Exceptions thrown by <see cref="GetSchema(string)" /> will be communicated via the returned Task Exception
/// property.
/// </summary>
/// <param name="collectionName">Specifies the name of the schema to return.</param>
/// <param name="cancellationToken">The cancellation instruction.</param>
/// <returns>A task representing the asynchronous operation.</returns>
public virtual Task<DataTable> GetSchemaAsync(
string collectionName,
CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled<DataTable>(cancellationToken);
}

try
{
return Task.FromResult(GetSchema(collectionName));
}
catch (Exception e)
{
return Task.FromException<DataTable>(e);
}
}

/// <summary>
/// This is the asynchronous version of <see cref="GetSchema(string, string[])" />.
/// Providers should override with an appropriate implementation.
/// The cancellation token can optionally be honored.
/// The default implementation invokes the synchronous <see cref="GetSchema(string, string[])" /> call and
/// returns a completed task.
/// The default implementation will return a cancelled task if passed an already cancelled cancellationToken.
/// Exceptions thrown by <see cref="GetSchema(string, string[])" /> will be communicated via the returned Task
/// Exception property.
/// </summary>
/// <param name="collectionName">Specifies the name of the schema to return.</param>
/// <param name="restrictionValues">Specifies a set of restriction values for the requested schema.</param>
/// <param name="cancellationToken">The cancellation instruction.</param>
/// <returns>A task representing the asynchronous operation.</returns>
public virtual Task<DataTable> GetSchemaAsync(string collectionName, string?[] restrictionValues,
CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled<DataTable>(cancellationToken);
}

try
{
return Task.FromResult(GetSchema(collectionName, restrictionValues));
}
catch (Exception e)
{
return Task.FromException<DataTable>(e);
}
}

protected virtual void OnStateChange(StateChangeEventArgs stateChange)
{
if (_suppressStateChangeForReconnection)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#nullable enable
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Threading.Tasks;
Expand Down Expand Up @@ -73,11 +74,77 @@ public virtual ValueTask DisposeAsync()

public abstract int GetOrdinal(string name);

/// <summary>
/// Returns a <see cref="DataTable" /> that describes the column metadata of the ><see cref="DbDataReader" />.
/// </summary>
/// <returns>A <see cref="DataTable" /> that describes the column metadata.</returns>
/// <exception cref="InvalidOperationException">The <see cref="DbDataReader" /> is closed.</exception>
/// <exception cref="IndexOutOfRangeException">The column index is out of range.</exception>
/// <exception cref="NotSupportedException">.NET Core only: This member is not supported.</exception>
public virtual DataTable GetSchemaTable()
{
throw new NotSupportedException();
}

/// <summary>
/// This is the asynchronous version of <see cref="GetSchemaTable()" />.
/// Providers should override with an appropriate implementation.
/// The cancellation token can optionally be honored.
/// The default implementation invokes the synchronous <see cref="GetSchemaTable()" /> call and
/// returns a completed task.
/// The default implementation will return a cancelled task if passed an already cancelled cancellationToken.
/// Exceptions thrown by <see cref="GetSchemaTable()" /> will be communicated via the returned Task
/// Exception property.
/// </summary>
/// <param name="cancellationToken">The cancellation instruction.</param>
/// <returns>A task representing the asynchronous operation.</returns>
public virtual Task<DataTable> GetSchemaTableAsync(CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled<DataTable>(cancellationToken);
}

try
{
return Task.FromResult(GetSchemaTable());
}
catch (Exception e)
{
return Task.FromException<DataTable>(e);
}
}

/// <summary>
/// This is the asynchronous version of <see cref="DbDataReaderExtensions.GetColumnSchema(DbDataReader)" />.
/// Providers should override with an appropriate implementation.
/// The cancellation token can optionally be honored.
/// The default implementation invokes the synchronous
/// <see cref="DbDataReaderExtensions.GetColumnSchema(DbDataReader)" /> call and returns a completed task.
/// The default implementation will return a cancelled task if passed an already cancelled cancellationToken.
/// Exceptions thrown by <see cref="DbDataReaderExtensions.GetColumnSchema(DbDataReader)" /> will be
/// communicated via the returned Task Exception property.
/// </summary>
/// <param name="cancellationToken">The cancellation instruction.</param>
/// <returns>A task representing the asynchronous operation.</returns>
public virtual Task<ReadOnlyCollection<DbColumn>> GetColumnSchemaAsync(
CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled<ReadOnlyCollection<DbColumn>>(cancellationToken);
}

try
{
return Task.FromResult(this.GetColumnSchema());
}
catch (Exception e)
{
return Task.FromException<ReadOnlyCollection<DbColumn>>(e);
}
}

public abstract bool GetBoolean(int ordinal);

public abstract byte GetByte(int ordinal);
Expand Down
Loading