Skip to content

Implement SqlConnection.GetSchemaAsync #3005

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

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
67 changes: 67 additions & 0 deletions doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2332,6 +2332,22 @@
A <see cref="T:System.Data.DataTable" /> that contains schema information.
</returns>
</GetSchema2>
<GetSchemaAsync>
<param name="cancellationToken">
The cancellation token.
</param>
<summary>
An asynchronous version of <see cref="M:Microsoft.Data.SqlClient.SqlConnection.GetSchema()" />, which returns schema information for the data source of this <see cref="T:Microsoft.Data.SqlClient.SqlConnection" />. For more information about scheme, see <see href="https://learn.microsoft.com/sql/connect/ado-net/sql-server-schema-collections">SQL Server Schema Collections</see>.
</summary>
<returns>
A task representing the asynchronous operation.
</returns>
<remarks>
<para>
For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see <see href="https://learn.microsoft.com/sql/connect/ado-net/asynchronous-programming">Asynchronous Programming</see>.
</para>
</remarks>
</GetSchemaAsync>
<GetSchemaCollectionName>
<param name="collectionName">
Specifies the name of the schema to return.
Expand Down Expand Up @@ -2617,6 +2633,28 @@
<paramref name="collectionName" /> is specified as null.
</exception>
</GetSchemaCollectionName>
<GetSchemaCollectionNameAsync>
<param name="collectionName">
Specifies the name of the schema to return.
</param>
<param name="cancellationToken">
The cancellation token.
</param>
<summary>
An asynchronous version of <see cref="M:Microsoft.Data.SqlClient.SqlConnection.GetSchema(string)" />, which returns schema information for the data source of this <see cref="T:Microsoft.Data.SqlClient.SqlConnection" /> using the specified string for the schema name.
</summary>
<returns>
A task representing the asynchronous operation.
</returns>
<remarks>
<para>
For more information about asynchronous programming in the .NET Framework Data Provider for SQL Server, see <see href="https://learn.microsoft.com/sql/connect/ado-net/asynchronous-programming">Asynchronous Programming</see>.
</para>
</remarks>
<exception cref="T:System.ArgumentException">
<paramref name="collectionName" /> is specified as null.
</exception>
</GetSchemaCollectionNameAsync>
<GetSchemaCollectionNameRestrictionValues>
<param name="collectionName">
Specifies the name of the schema to return.
Expand Down Expand Up @@ -2646,6 +2684,35 @@
</exception>
<seealso cref="M:Microsoft.Data.SqlClient.SqlConnection.GetSchema" />
</GetSchemaCollectionNameRestrictionValues>
<GetSchemaCollectionNameRestrictionValuesAsync>
<param name="collectionName">
Specifies the name of the schema to return.
</param>
<param name="restrictionValues">
A set of restriction values for the requested schema.
</param>
<param name="cancellationToken">
The cancellation token.
</param>
<summary>
An asynchronous version of <see cref="M:Microsoft.Data.SqlClient.SqlConnection.GetSchema(string, string[])" />, which returns schema information for the data source of this <see cref="T:Microsoft.Data.SqlClient.SqlConnection" /> using the specified string for the schema name and the specified string array for the restriction values.
</summary>
<returns>
A task representing the asynchronous operation.
</returns>
<remarks>
<para>
The <paramref name="restrictionValues" /> parameter can supply <i>n</i> 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 <see langword="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 need to pass in the following values: 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 <see langword="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>
</remarks>
<exception cref="T:System.ArgumentException">
<paramref name="collectionName" /> is specified as null.
</exception>
<seealso cref="M:Microsoft.Data.SqlClient.SqlConnection.GetSchema" />
</GetSchemaCollectionNameRestrictionValuesAsync>
<InfoMessage>
<summary>
Occurs when SQL Server returns a warning or informational message.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -965,10 +965,16 @@ public event Microsoft.Data.SqlClient.SqlInfoMessageEventHandler InfoMessage { a
protected override System.Data.Common.DbCommand CreateDbCommand() { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchema2/*'/>
public override System.Data.DataTable GetSchema() { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaAsync/*'/>
public override System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(System.Threading.CancellationToken cancellationToken = default) { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionName/*'/>
public override System.Data.DataTable GetSchema(string collectionName) { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameAsync/*'/>
public override System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(string collectionName, System.Threading.CancellationToken cancellationToken = default) { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValues/*'/>
public override System.Data.DataTable GetSchema(string collectionName, string[] restrictionValues) { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValuesAsync/*'/>
public override System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(string collectionName, string[] restrictionValues, System.Threading.CancellationToken cancellationToken = default) { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/Open/*'/>
public override void Open() { }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/OpenWithOverrides/*'/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1781,19 +1781,38 @@ public override DataTable GetSchema()
return GetSchema(DbMetaDataCollectionNames.MetaDataCollections, null);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaAsync/*' />
public override Task<DataTable> GetSchemaAsync(CancellationToken cancellationToken = default)
{
return GetSchemaAsync(DbMetaDataCollectionNames.MetaDataCollections, cancellationToken);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionName/*' />
public override DataTable GetSchema(string collectionName)
{
return GetSchema(collectionName, null);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameAsync/*' />
public override Task<DataTable> GetSchemaAsync(string collectionName, CancellationToken cancellationToken = default)
{
return GetSchemaAsync(collectionName, null, cancellationToken);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValues/*' />
public override DataTable GetSchema(string collectionName, string[] restrictionValues)
{
SqlClientEventSource.Log.TryTraceEvent("SqlConnection.GetSchema | Info | Object Id {0}, Collection Name '{1}'", ObjectID, collectionName);
return InnerConnection.GetSchema(ConnectionFactory, PoolGroup, this, collectionName, restrictionValues);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValuesAsync/*' />
public override Task<DataTable> GetSchemaAsync(string collectionName, string[] restrictionValues, CancellationToken cancellationToken = default)
{
SqlClientEventSource.Log.TryTraceEvent("SqlConnection.GetSchemaAsync | Info | Object Id {0}, Collection Name '{1}'", ObjectID, collectionName);
return InnerConnection.GetSchemaAsync(ConnectionFactory, PoolGroup, this, collectionName, restrictionValues, cancellationToken);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/CanCreateBatch/*'/>
public override bool CanCreateBatch => true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -875,10 +875,16 @@ public void EnlistDistributedTransaction(System.EnterpriseServices.ITransaction
public override void EnlistTransaction(System.Transactions.Transaction transaction) { }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchema2/*'/>
public override System.Data.DataTable GetSchema() { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaAsync/*'/>
public System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(System.Threading.CancellationToken cancellationToken = default) { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionName/*'/>
public override System.Data.DataTable GetSchema(string collectionName) { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameAsync/*'/>
public System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(string collectionName, System.Threading.CancellationToken cancellationToken = default) { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValues/*'/>
public override System.Data.DataTable GetSchema(string collectionName, string[] restrictionValues) { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValuesAsync/*'/>
public System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(string collectionName, string[] restrictionValues, System.Threading.CancellationToken cancellationToken = default) { throw null; }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/Open/*'/>
public override void Open() { }
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/OpenWithOverrides/*'/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2015,6 +2015,46 @@ private Task InternalOpenAsync(CancellationToken cancellationToken)
}
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchema2/*' />
public override DataTable GetSchema()
{
return GetSchema(DbMetaDataCollectionNames.MetaDataCollections, null);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaAsync/*' />
public Task<DataTable> GetSchemaAsync(CancellationToken cancellationToken = default)
{
return GetSchemaAsync(DbMetaDataCollectionNames.MetaDataCollections, cancellationToken);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionName/*' />
public override DataTable GetSchema(string collectionName)
{
return GetSchema(collectionName, null);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameAsync/*' />
public Task<DataTable> GetSchemaAsync(string collectionName, CancellationToken cancellationToken = default)
{
return GetSchemaAsync(collectionName, null, cancellationToken);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValues/*' />
public override DataTable GetSchema(string collectionName, string[] restrictionValues)
{
// NOTE: This is virtual because not all providers may choose to support
// returning schema data
SqlConnection.ExecutePermission.Demand();
return InnerConnection.GetSchema(ConnectionFactory, PoolGroup, this, collectionName, restrictionValues);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValuesAsync/*' />
public Task<DataTable> GetSchemaAsync(string collectionName, string[] restrictionValues, CancellationToken cancellationToken = default)
{
SqlConnection.ExecutePermission.Demand();
return InnerConnection.GetSchemaAsync(ConnectionFactory, PoolGroup, this, collectionName, restrictionValues, cancellationToken);
}

private class OpenAsyncRetry
{
SqlConnection _parent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,27 +311,6 @@ internal DbMetaDataFactory GetMetaDataFactoryInternal(DbConnectionInternal inter
return GetMetaDataFactory(internalConnection);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchema2/*' />
override public DataTable GetSchema()
{
return this.GetSchema(DbMetaDataCollectionNames.MetaDataCollections, null);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionName/*' />
override public DataTable GetSchema(string collectionName)
{
return this.GetSchema(collectionName, null);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValues/*' />
override public DataTable GetSchema(string collectionName, string[] restrictionValues)
{
// NOTE: This is virtual because not all providers may choose to support
// returning schema data
SqlConnection.ExecutePermission.Demand();
return InnerConnection.GetSchema(ConnectionFactory, PoolGroup, this, collectionName, restrictionValues);
}

internal void NotifyWeakReference(int message)
{
InnerConnection.NotifyWeakReference(message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.Data.ProviderBase
Expand Down Expand Up @@ -37,6 +38,9 @@ internal override void CloseConnection(DbConnection owningObject, DbConnectionFa
protected internal override DataTable GetSchema(DbConnectionFactory factory, DbConnectionPoolGroup poolGroup, DbConnection outerConnection, string collectionName, string[] restrictions)
=> throw ADP.ClosedConnectionError();

protected internal override Task<DataTable> GetSchemaAsync(DbConnectionFactory factory, DbConnectionPoolGroup poolGroup, DbConnection outerConnection, string collectionName, string[] restrictions, CancellationToken cancellationToken)
=> throw ADP.ClosedConnectionError();

protected override DbReferenceCollection CreateReferenceCollection() => throw ADP.ClosedConnectionError();

internal override bool TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,22 @@ protected internal virtual DataTable GetSchema(
return metaDataFactory.GetSchema(outerConnection, collectionName, restrictions);
}

protected internal virtual Task<DataTable> GetSchemaAsync(
DbConnectionFactory factory,
DbConnectionPoolGroup poolGroup,
DbConnection outerConnection,
string collectionName,
string[] restrictions,
CancellationToken cancellationToken)
{
Debug.Assert(outerConnection is not null, "outerConnection may not be null.");

DbMetaDataFactory metaDataFactory = factory.GetMetaDataFactory(poolGroup, this);
Debug.Assert(metaDataFactory is not null, "metaDataFactory may not be null.");

return metaDataFactory.GetSchemaAsync(outerConnection, collectionName, restrictions, cancellationToken);
}

protected virtual bool ObtainAdditionalLocksForClose()
{
// No additional locks in default implementation
Expand Down
Loading
Loading