@@ -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 $ """
486498SELECT @@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