Skip to content

Commit b2a60a3

Browse files
committed
Addressed the Copilot comment from the original PR #3719.
1 parent 6f6f5bb commit b2a60a3

1 file changed

Lines changed: 37 additions & 25 deletions

File tree

  • src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -477,11 +477,23 @@ private string CreateInitialQuery()
477477

478478
string objectName = ADP.BuildMultiPartName(parts);
479479
string escapedObjectName = SqlServerEscapeHelper.EscapeStringAsLiteral(objectName);
480-
// Specify the column names explicitly. This is to ensure that we can map to hidden columns (e.g. columns in temporal tables.)
481-
// If the target table doesn't exist, OBJECT_ID will return NULL and @Column_Names will remain non-null. The subsequent SELECT *
482-
// query will then continue to fail with "Invalid object name" rather than with an unusual error because the query being executed
483-
// is NULL.
484-
// Some hidden columns (e.g. SQL Graph columns) cannot be selected, so we need to exclude them explicitly.
480+
// Specify the column names explicitly. This is to ensure that we can map to hidden
481+
// columns (e.g. columns in temporal tables.) If the target table doesn't exist,
482+
// OBJECT_ID will return NULL and @Column_Names will remain non-null. The subsequent
483+
// SELECT * query will then continue to fail with "Invalid object name" rather than with
484+
// an unusual error because the query being executed is NULL.
485+
//
486+
// Some hidden columns (e.g. SQL Graph columns) cannot be selected, so we need to
487+
// exclude them explicitly. The graph_type values excluded below are internal graph
488+
// columns that cannot be selected directly:
489+
//
490+
// 1 = GRAPH_ID
491+
// 3 = GRAPH_FROM_ID
492+
// 4 = GRAPH_FROM_OBJ_ID
493+
// 6 = GRAPH_TO_ID
494+
// 7 = GRAPH_TO_OBJ_ID
495+
//
496+
// See: https://learn.microsoft.com/sql/relational-databases/graphs/sql-graph-architecture#syscolumns
485497
return $"""
486498
SELECT @@TRANCOUNT;
487499
@@ -627,7 +639,7 @@ private string AnalyzeTargetAndCreateUpdateBulkCommand(BulkCopySimpleResultSet i
627639

628640
bool matched = false;
629641
bool rejected = false;
630-
642+
631643
// Look for a local match for the remote column.
632644
for (int j = 0; j < _localColumnMappings.Count; ++j)
633645
{
@@ -647,7 +659,7 @@ private string AnalyzeTargetAndCreateUpdateBulkCommand(BulkCopySimpleResultSet i
647659

648660
// Remove it from our unmatched set.
649661
unmatchedColumns.Remove(localColumn.DestinationColumn);
650-
662+
651663
// Check for column types that we refuse to bulk load, even
652664
// though we found a match.
653665
//
@@ -1440,7 +1452,7 @@ private void RunParserReliably(BulkCopySimpleResultSet bulkCopyHandler = null)
14401452
try
14411453
{
14421454
// @TODO: CER Exception Handling was removed here (see GH#3581)
1443-
_parser.Run(RunBehavior.UntilDone, null, null, bulkCopyHandler, _stateObj);
1455+
_parser.Run(RunBehavior.UntilDone, null, null, bulkCopyHandler, _stateObj);
14441456
}
14451457
finally
14461458
{
@@ -1763,7 +1775,7 @@ public void WriteToServer(DbDataReader reader)
17631775
try
17641776
{
17651777
statistics = SqlStatistics.StartTimer(Statistics);
1766-
1778+
17671779
ResetWriteToServerGlobalVariables();
17681780
_rowSource = reader;
17691781
_dbDataReaderRowSource = reader;
@@ -1799,13 +1811,13 @@ public void WriteToServer(IDataReader reader)
17991811
try
18001812
{
18011813
statistics = SqlStatistics.StartTimer(Statistics);
1802-
1814+
18031815
ResetWriteToServerGlobalVariables();
18041816
_rowSource = reader;
18051817
_sqlDataReaderRowSource = _rowSource as SqlDataReader;
18061818
_dbDataReaderRowSource = _rowSource as DbDataReader;
18071819
_rowSourceType = ValueSourceType.IDataReader;
1808-
1820+
18091821
WriteRowSourceToServerAsync(reader.FieldCount, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false;
18101822
}
18111823
finally
@@ -1921,7 +1933,7 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok
19211933
try
19221934
{
19231935
statistics = SqlStatistics.StartTimer(Statistics);
1924-
1936+
19251937
ResetWriteToServerGlobalVariables();
19261938
if (rows.Length == 0)
19271939
{
@@ -1938,9 +1950,9 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok
19381950
_rowSourceType = ValueSourceType.RowArray;
19391951
_rowEnumerator = rows.GetEnumerator();
19401952
_isAsyncBulkCopy = true;
1941-
1953+
19421954
// It returns Task since _isAsyncBulkCopy = true;
1943-
return WriteRowSourceToServerAsync(table.Columns.Count, cancellationToken);
1955+
return WriteRowSourceToServerAsync(table.Columns.Count, cancellationToken);
19441956
}
19451957
finally
19461958
{
@@ -1967,19 +1979,19 @@ public Task WriteToServerAsync(DbDataReader reader, CancellationToken cancellati
19671979
{
19681980
throw SQL.BulkLoadPendingOperation();
19691981
}
1970-
1982+
19711983
SqlStatistics statistics = Statistics;
19721984
try
19731985
{
19741986
statistics = SqlStatistics.StartTimer(Statistics);
1975-
1987+
19761988
ResetWriteToServerGlobalVariables();
19771989
_rowSource = reader;
19781990
_sqlDataReaderRowSource = reader as SqlDataReader;
19791991
_dbDataReaderRowSource = reader;
19801992
_rowSourceType = ValueSourceType.DbDataReader;
19811993
_isAsyncBulkCopy = true;
1982-
1994+
19831995
// It returns Task since _isAsyncBulkCopy = true;
19841996
return WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken);
19851997
}
@@ -2019,7 +2031,7 @@ public Task WriteToServerAsync(IDataReader reader, CancellationToken cancellatio
20192031
_dbDataReaderRowSource = _rowSource as DbDataReader;
20202032
_rowSourceType = ValueSourceType.IDataReader;
20212033
_isAsyncBulkCopy = true;
2022-
2034+
20232035
// It returns Task since _isAsyncBulkCopy = true;
20242036
return WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken);
20252037
}
@@ -2059,15 +2071,15 @@ public Task WriteToServerAsync(DataTable table, DataRowState rowState, Cancellat
20592071
try
20602072
{
20612073
statistics = SqlStatistics.StartTimer(Statistics);
2062-
2074+
20632075
ResetWriteToServerGlobalVariables();
20642076
_rowStateToSkip = ((rowState == 0) || (rowState == DataRowState.Deleted)) ? DataRowState.Deleted : ~rowState | DataRowState.Deleted;
20652077
_rowSource = table;
20662078
_dataTableSource = table;
20672079
_rowSourceType = ValueSourceType.DataTable;
20682080
_rowEnumerator = table.Rows.GetEnumerator();
20692081
_isAsyncBulkCopy = true;
2070-
2082+
20712083
// It returns Task since _isAsyncBulkCopy = true;
20722084
return WriteRowSourceToServerAsync(table.Columns.Count, cancellationToken);
20732085
}
@@ -2117,7 +2129,7 @@ private Task WriteRowSourceToServerAsync(int columnCount, CancellationToken ctok
21172129

21182130
bool finishedSynchronously = true;
21192131
_isBulkCopyingInProgress = true;
2120-
2132+
21212133
CreateOrValidateConnection(nameof(WriteToServer));
21222134

21232135
SqlConnectionInternal internalConnection = _connection.GetOpenTdsConnection();
@@ -3068,11 +3080,11 @@ private void WriteToServerInternalRestAsync(CancellationToken cts, TaskCompletio
30683080

30693081
// No need to cancel timer since SqlBulkCopy creates specific task source for reconnection.
30703082
AsyncHelper.SetTimeoutExceptionWithState(
3071-
completion: cancellableReconnectTS,
3083+
completion: cancellableReconnectTS,
30723084
timeout: BulkCopyTimeout,
30733085
state: _destinationTableName,
3074-
onFailure: static state =>
3075-
SQL.BulkLoadInvalidDestinationTable((string)state, SQL.CR_ReconnectTimeout()),
3086+
onFailure: static state =>
3087+
SQL.BulkLoadInvalidDestinationTable((string)state, SQL.CR_ReconnectTimeout()),
30763088
cancellationToken: CancellationToken.None
30773089
);
30783090

@@ -3245,7 +3257,7 @@ private Task WriteToServerInternalAsync(CancellationToken ctoken)
32453257
}
32463258
return resultTask;
32473259
}
3248-
3260+
32493261
private void ResetWriteToServerGlobalVariables()
32503262
{
32513263
_dataTableSource = null;

0 commit comments

Comments
 (0)