Skip to content

Commit 8ed0162

Browse files
authored
Feature | Implement SqlConnection.GetSchemaAsync (#3005)
1 parent 49f640e commit 8ed0162

11 files changed

Lines changed: 356 additions & 72 deletions

File tree

doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1371,12 +1371,28 @@ For more information on working with events, see [Connection Events](https://lea
13711371
</FireInfoMessageEventOnUserErrors>
13721372
<GetSchema2>
13731373
<summary>
1374-
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>.
1374+
Returns schema information for the data source of this <see cref="T:Microsoft.Data.SqlClient.SqlConnection" />. For more information about schemas, see <see href="https://learn.microsoft.com/sql/connect/ado-net/sql-server-schema-collections">SQL Server Schema Collections</see>.
13751375
</summary>
13761376
<returns>
13771377
A <see cref="T:System.Data.DataTable" /> that contains schema information.
13781378
</returns>
13791379
</GetSchema2>
1380+
<GetSchemaAsync>
1381+
<param name="cancellationToken">
1382+
The cancellation token.
1383+
</param>
1384+
<summary>
1385+
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 schemas, see <see href="https://learn.microsoft.com/sql/connect/ado-net/sql-server-schema-collections">SQL Server Schema Collections</see>.
1386+
</summary>
1387+
<returns>
1388+
A task representing the asynchronous operation.
1389+
</returns>
1390+
<remarks>
1391+
<para>
1392+
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>.
1393+
</para>
1394+
</remarks>
1395+
</GetSchemaAsync>
13801396
<GetSchemaCollectionName>
13811397
<param name="collectionName">
13821398
Specifies the name of the schema to return.
@@ -1662,6 +1678,28 @@ For more information on working with events, see [Connection Events](https://lea
16621678
<paramref name="collectionName" /> is specified as null.
16631679
</exception>
16641680
</GetSchemaCollectionName>
1681+
<GetSchemaCollectionNameAsync>
1682+
<param name="collectionName">
1683+
Specifies the name of the schema to return.
1684+
</param>
1685+
<param name="cancellationToken">
1686+
The cancellation token.
1687+
</param>
1688+
<summary>
1689+
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.
1690+
</summary>
1691+
<returns>
1692+
A task representing the asynchronous operation.
1693+
</returns>
1694+
<remarks>
1695+
<para>
1696+
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>.
1697+
</para>
1698+
</remarks>
1699+
<exception cref="T:System.ArgumentException">
1700+
<paramref name="collectionName" /> is specified as null.
1701+
</exception>
1702+
</GetSchemaCollectionNameAsync>
16651703
<GetSchemaCollectionNameRestrictionValues>
16661704
<param name="collectionName">
16671705
Specifies the name of the schema to return.
@@ -1691,6 +1729,35 @@ For more information on working with events, see [Connection Events](https://lea
16911729
</exception>
16921730
<seealso cref="M:Microsoft.Data.SqlClient.SqlConnection.GetSchema" />
16931731
</GetSchemaCollectionNameRestrictionValues>
1732+
<GetSchemaCollectionNameRestrictionValuesAsync>
1733+
<param name="collectionName">
1734+
Specifies the name of the schema to return.
1735+
</param>
1736+
<param name="restrictionValues">
1737+
A set of restriction values for the requested schema.
1738+
</param>
1739+
<param name="cancellationToken">
1740+
The cancellation token.
1741+
</param>
1742+
<summary>
1743+
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.
1744+
</summary>
1745+
<returns>
1746+
A task representing the asynchronous operation.
1747+
</returns>
1748+
<remarks>
1749+
<para>
1750+
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.
1751+
</para>
1752+
<para>
1753+
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.
1754+
</para>
1755+
</remarks>
1756+
<exception cref="T:System.ArgumentException">
1757+
<paramref name="collectionName" /> is specified as null.
1758+
</exception>
1759+
<seealso cref="M:Microsoft.Data.SqlClient.SqlConnection.GetSchema" />
1760+
</GetSchemaCollectionNameRestrictionValuesAsync>
16941761
<InfoMessage>
16951762
<summary>
16961763
Occurs when SQL Server returns a warning or informational message.

src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,21 @@ public event Microsoft.Data.SqlClient.SqlInfoMessageEventHandler InfoMessage { a
10991099
public override System.Data.DataTable GetSchema(string collectionName) { throw null; }
11001100
/// <include file='../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValues/*'/>
11011101
public override System.Data.DataTable GetSchema(string collectionName, string[] restrictionValues) { throw null; }
1102+
#if NET
1103+
/// <include file='../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaAsync/*'/>
1104+
public override System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(System.Threading.CancellationToken cancellationToken = default) { throw null; }
1105+
/// <include file='../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameAsync/*'/>
1106+
public override System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(string collectionName, System.Threading.CancellationToken cancellationToken = default) { throw null; }
1107+
/// <include file='../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValuesAsync/*'/>
1108+
public override System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(string collectionName, string[] restrictionValues, System.Threading.CancellationToken cancellationToken = default) { throw null; }
1109+
#else
1110+
/// <include file='../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaAsync/*'/>
1111+
public System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(System.Threading.CancellationToken cancellationToken = default) { throw null; }
1112+
/// <include file='../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameAsync/*'/>
1113+
public System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(string collectionName, System.Threading.CancellationToken cancellationToken = default) { throw null; }
1114+
/// <include file='../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValuesAsync/*'/>
1115+
public System.Threading.Tasks.Task<System.Data.DataTable> GetSchemaAsync(string collectionName, string[] restrictionValues, System.Threading.CancellationToken cancellationToken = default) { throw null; }
1116+
#endif
11021117
/// <include file='../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/Open/*'/>
11031118
public override void Open() { }
11041119
/// <include file='../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/OpenWithOverrides/*'/>

src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionClosed.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Data;
66
using System.Data.Common;
77
using System.Diagnostics;
8+
using System.Threading;
89
using System.Threading.Tasks;
910
using Microsoft.Data.Common;
1011
using Microsoft.Data.Common.ConnectionString;
@@ -48,6 +49,15 @@ protected internal override DataTable GetSchema(
4849
throw ADP.ClosedConnectionError();
4950
}
5051

52+
protected internal override Task<DataTable> GetSchemaAsync(
53+
SqlConnectionFactory factory,
54+
DbConnectionPoolGroup poolGroup,
55+
DbConnection outerConnection,
56+
string collectionName,
57+
string[] restrictions,
58+
CancellationToken cancellationToken)
59+
=> throw ADP.ClosedConnectionError();
60+
5161
protected override DbReferenceCollection CreateReferenceCollection() => throw ADP.ClosedConnectionError();
5262

5363
internal override bool TryOpenConnection(

src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionInternal.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,22 @@ protected internal virtual DataTable GetSchema(
878878
return metaDataFactory.GetSchema(outerConnection, collectionName, restrictions);
879879
}
880880

881+
protected internal virtual Task<DataTable> GetSchemaAsync(
882+
SqlConnectionFactory factory,
883+
DbConnectionPoolGroup poolGroup,
884+
DbConnection outerConnection,
885+
string collectionName,
886+
string[] restrictions,
887+
CancellationToken cancellationToken)
888+
{
889+
Debug.Assert(outerConnection is not null, "outerConnection may not be null.");
890+
891+
SqlMetaDataFactory metaDataFactory = factory.GetMetaDataFactory(poolGroup, this);
892+
Debug.Assert(metaDataFactory is not null, "metaDataFactory may not be null.");
893+
894+
return metaDataFactory.GetSchemaAsync(outerConnection, collectionName, restrictions, cancellationToken);
895+
}
896+
881897
protected virtual bool ObtainAdditionalLocksForClose()
882898
{
883899
// No additional locks in default implementation

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,12 +2026,32 @@ public override DataTable GetSchema()
20262026
return GetSchema(DbMetaDataCollectionNames.MetaDataCollections, null);
20272027
}
20282028

2029+
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaAsync/*' />
2030+
#if NET
2031+
public override Task<DataTable> GetSchemaAsync(CancellationToken cancellationToken = default)
2032+
#else
2033+
public Task<DataTable> GetSchemaAsync(CancellationToken cancellationToken = default)
2034+
#endif
2035+
{
2036+
return GetSchemaAsync(DbMetaDataCollectionNames.MetaDataCollections, cancellationToken);
2037+
}
2038+
20292039
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionName/*' />
20302040
public override DataTable GetSchema(string collectionName)
20312041
{
20322042
return GetSchema(collectionName, null);
20332043
}
20342044

2045+
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameAsync/*' />
2046+
#if NET
2047+
public override Task<DataTable> GetSchemaAsync(string collectionName, CancellationToken cancellationToken = default)
2048+
#else
2049+
public Task<DataTable> GetSchemaAsync(string collectionName, CancellationToken cancellationToken = default)
2050+
#endif
2051+
{
2052+
return GetSchemaAsync(collectionName, null, cancellationToken);
2053+
}
2054+
20352055
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValues/*' />
20362056
public override DataTable GetSchema(string collectionName, string[] restrictionValues)
20372057
{
@@ -2042,6 +2062,17 @@ public override DataTable GetSchema(string collectionName, string[] restrictionV
20422062
return InnerConnection.GetSchema(ConnectionFactory, PoolGroup, this, collectionName, restrictionValues);
20432063
}
20442064

2065+
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/GetSchemaCollectionNameRestrictionValuesAsync/*' />
2066+
#if NET
2067+
public override Task<DataTable> GetSchemaAsync(string collectionName, string[] restrictionValues, CancellationToken cancellationToken = default)
2068+
#else
2069+
public Task<DataTable> GetSchemaAsync(string collectionName, string[] restrictionValues, CancellationToken cancellationToken = default)
2070+
#endif
2071+
{
2072+
SqlClientEventSource.Log.TryTraceEvent("SqlConnection.GetSchemaAsync | Info | Object Id {0}, Collection Name '{1}'", ObjectID, collectionName);
2073+
return InnerConnection.GetSchemaAsync(ConnectionFactory, PoolGroup, this, collectionName, restrictionValues, cancellationToken);
2074+
}
2075+
20452076
#if NET
20462077
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/CanCreateBatch/*'/>
20472078
public override bool CanCreateBatch => true;

0 commit comments

Comments
 (0)