Skip to content

Commit 5376a04

Browse files
authored
Fix | Fixed SqlBulkCopy.WriteToServer to ensure successful completion of consecutive calls to it. (#2375)
1 parent 2ddf723 commit 5376a04

File tree

4 files changed

+179
-29
lines changed

4 files changed

+179
-29
lines changed

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

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,14 +1640,12 @@ public void WriteToServer(DbDataReader reader)
16401640
try
16411641
{
16421642
statistics = SqlStatistics.StartTimer(Statistics);
1643+
ResetWriteToServerGlobalVariables();
16431644
_rowSource = reader;
16441645
_dbDataReaderRowSource = reader;
16451646
_sqlDataReaderRowSource = reader as SqlDataReader;
1646-
1647-
_dataTableSource = null;
16481647
_rowSourceType = ValueSourceType.DbDataReader;
16491648

1650-
_isAsyncBulkCopy = false;
16511649
WriteRowSourceToServerAsync(reader.FieldCount, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false;
16521650
}
16531651
finally
@@ -1673,12 +1671,11 @@ public void WriteToServer(IDataReader reader)
16731671
try
16741672
{
16751673
statistics = SqlStatistics.StartTimer(Statistics);
1674+
ResetWriteToServerGlobalVariables();
16761675
_rowSource = reader;
16771676
_sqlDataReaderRowSource = _rowSource as SqlDataReader;
16781677
_dbDataReaderRowSource = _rowSource as DbDataReader;
1679-
_dataTableSource = null;
16801678
_rowSourceType = ValueSourceType.IDataReader;
1681-
_isAsyncBulkCopy = false;
16821679
WriteRowSourceToServerAsync(reader.FieldCount, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false;
16831680
}
16841681
finally
@@ -1707,13 +1704,12 @@ public void WriteToServer(DataTable table, DataRowState rowState)
17071704
try
17081705
{
17091706
statistics = SqlStatistics.StartTimer(Statistics);
1707+
ResetWriteToServerGlobalVariables();
17101708
_rowStateToSkip = ((rowState == 0) || (rowState == DataRowState.Deleted)) ? DataRowState.Deleted : ~rowState | DataRowState.Deleted;
17111709
_rowSource = table;
17121710
_dataTableSource = table;
1713-
_sqlDataReaderRowSource = null;
17141711
_rowSourceType = ValueSourceType.DataTable;
17151712
_rowEnumerator = table.Rows.GetEnumerator();
1716-
_isAsyncBulkCopy = false;
17171713

17181714
WriteRowSourceToServerAsync(table.Columns.Count, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false;
17191715
}
@@ -1746,16 +1742,14 @@ public void WriteToServer(DataRow[] rows)
17461742
try
17471743
{
17481744
statistics = SqlStatistics.StartTimer(Statistics);
1749-
1745+
ResetWriteToServerGlobalVariables();
17501746
DataTable table = rows[0].Table;
17511747
Debug.Assert(null != table, "How can we have rows without a table?");
17521748
_rowStateToSkip = DataRowState.Deleted; // Don't allow deleted rows
17531749
_rowSource = rows;
17541750
_dataTableSource = table;
1755-
_sqlDataReaderRowSource = null;
17561751
_rowSourceType = ValueSourceType.RowArray;
17571752
_rowEnumerator = rows.GetEnumerator();
1758-
_isAsyncBulkCopy = false;
17591753

17601754
WriteRowSourceToServerAsync(table.Columns.Count, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false;
17611755
}
@@ -1787,7 +1781,7 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok
17871781
try
17881782
{
17891783
statistics = SqlStatistics.StartTimer(Statistics);
1790-
1784+
ResetWriteToServerGlobalVariables();
17911785
if (rows.Length == 0)
17921786
{
17931787
return cancellationToken.IsCancellationRequested ?
@@ -1800,7 +1794,6 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok
18001794
_rowStateToSkip = DataRowState.Deleted; // Don't allow deleted rows
18011795
_rowSource = rows;
18021796
_dataTableSource = table;
1803-
_sqlDataReaderRowSource = null;
18041797
_rowSourceType = ValueSourceType.RowArray;
18051798
_rowEnumerator = rows.GetEnumerator();
18061799
_isAsyncBulkCopy = true;
@@ -1834,10 +1827,10 @@ public Task WriteToServerAsync(DbDataReader reader, CancellationToken cancellati
18341827
try
18351828
{
18361829
statistics = SqlStatistics.StartTimer(Statistics);
1830+
ResetWriteToServerGlobalVariables();
18371831
_rowSource = reader;
18381832
_sqlDataReaderRowSource = reader as SqlDataReader;
18391833
_dbDataReaderRowSource = reader;
1840-
_dataTableSource = null;
18411834
_rowSourceType = ValueSourceType.DbDataReader;
18421835
_isAsyncBulkCopy = true;
18431836
resultTask = WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken); // It returns Task since _isAsyncBulkCopy = true;
@@ -1871,10 +1864,10 @@ public Task WriteToServerAsync(IDataReader reader, CancellationToken cancellatio
18711864
try
18721865
{
18731866
statistics = SqlStatistics.StartTimer(Statistics);
1867+
ResetWriteToServerGlobalVariables();
18741868
_rowSource = reader;
18751869
_sqlDataReaderRowSource = _rowSource as SqlDataReader;
18761870
_dbDataReaderRowSource = _rowSource as DbDataReader;
1877-
_dataTableSource = null;
18781871
_rowSourceType = ValueSourceType.IDataReader;
18791872
_isAsyncBulkCopy = true;
18801873
resultTask = WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken); // It returns Task since _isAsyncBulkCopy = true;
@@ -1914,9 +1907,9 @@ public Task WriteToServerAsync(DataTable table, DataRowState rowState, Cancellat
19141907
try
19151908
{
19161909
statistics = SqlStatistics.StartTimer(Statistics);
1910+
ResetWriteToServerGlobalVariables();
19171911
_rowStateToSkip = ((rowState == 0) || (rowState == DataRowState.Deleted)) ? DataRowState.Deleted : ~rowState | DataRowState.Deleted;
19181912
_rowSource = table;
1919-
_sqlDataReaderRowSource = null;
19201913
_dataTableSource = table;
19211914
_rowSourceType = ValueSourceType.DataTable;
19221915
_rowEnumerator = table.Rows.GetEnumerator();
@@ -3093,5 +3086,17 @@ private Task WriteToServerInternalAsync(CancellationToken ctoken)
30933086
}
30943087
return resultTask;
30953088
}
3089+
3090+
private void ResetWriteToServerGlobalVariables()
3091+
{
3092+
_dataTableSource = null;
3093+
_dbDataReaderRowSource = null;
3094+
_isAsyncBulkCopy = false;
3095+
_rowEnumerator = null;
3096+
_rowSource = null;
3097+
_rowSourceType = ValueSourceType.Unspecified;
3098+
_sqlDataReaderRowSource = null;
3099+
_sqlDataReaderRowSource = null;
3100+
}
30963101
}
30973102
}

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

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,6 +1689,7 @@ public void WriteToServer(DbDataReader reader)
16891689
try
16901690
{
16911691
statistics = SqlStatistics.StartTimer(Statistics);
1692+
ResetWriteToServerGlobalVariables();
16921693
_rowSource = reader;
16931694
_dbDataReaderRowSource = reader;
16941695
_sqlDataReaderRowSource = reader as SqlDataReader;
@@ -1697,10 +1698,8 @@ public void WriteToServer(DbDataReader reader)
16971698
{
16981699
_rowSourceIsSqlDataReaderSmi = _sqlDataReaderRowSource is SqlDataReaderSmi;
16991700
}
1700-
_dataTableSource = null;
17011701
_rowSourceType = ValueSourceType.DbDataReader;
17021702

1703-
_isAsyncBulkCopy = false;
17041703
WriteRowSourceToServerAsync(reader.FieldCount, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false;
17051704
}
17061705
finally
@@ -1728,16 +1727,15 @@ public void WriteToServer(IDataReader reader)
17281727
try
17291728
{
17301729
statistics = SqlStatistics.StartTimer(Statistics);
1730+
ResetWriteToServerGlobalVariables();
17311731
_rowSource = reader;
17321732
_sqlDataReaderRowSource = _rowSource as SqlDataReader;
17331733
if (_sqlDataReaderRowSource != null)
17341734
{
17351735
_rowSourceIsSqlDataReaderSmi = _sqlDataReaderRowSource is SqlDataReaderSmi;
17361736
}
17371737
_dbDataReaderRowSource = _rowSource as DbDataReader;
1738-
_dataTableSource = null;
17391738
_rowSourceType = ValueSourceType.IDataReader;
1740-
_isAsyncBulkCopy = false;
17411739
WriteRowSourceToServerAsync(reader.FieldCount, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false;
17421740
}
17431741
finally
@@ -1768,13 +1766,12 @@ public void WriteToServer(DataTable table, DataRowState rowState)
17681766
try
17691767
{
17701768
statistics = SqlStatistics.StartTimer(Statistics);
1769+
ResetWriteToServerGlobalVariables();
17711770
_rowStateToSkip = ((rowState == 0) || (rowState == DataRowState.Deleted)) ? DataRowState.Deleted : ~rowState | DataRowState.Deleted;
17721771
_rowSource = table;
17731772
_dataTableSource = table;
1774-
_sqlDataReaderRowSource = null;
17751773
_rowSourceType = ValueSourceType.DataTable;
17761774
_rowEnumerator = table.Rows.GetEnumerator();
1777-
_isAsyncBulkCopy = false;
17781775

17791776
WriteRowSourceToServerAsync(table.Columns.Count, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false;
17801777
}
@@ -1809,16 +1806,14 @@ public void WriteToServer(DataRow[] rows)
18091806
try
18101807
{
18111808
statistics = SqlStatistics.StartTimer(Statistics);
1812-
1809+
ResetWriteToServerGlobalVariables();
18131810
DataTable table = rows[0].Table;
18141811
Debug.Assert(null != table, "How can we have rows without a table?");
18151812
_rowStateToSkip = DataRowState.Deleted; // Don't allow deleted rows
18161813
_rowSource = rows;
18171814
_dataTableSource = table;
1818-
_sqlDataReaderRowSource = null;
18191815
_rowSourceType = ValueSourceType.RowArray;
18201816
_rowEnumerator = rows.GetEnumerator();
1821-
_isAsyncBulkCopy = false;
18221817

18231818
WriteRowSourceToServerAsync(table.Columns.Count, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false;
18241819
}
@@ -1851,7 +1846,7 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok
18511846
try
18521847
{
18531848
statistics = SqlStatistics.StartTimer(Statistics);
1854-
1849+
ResetWriteToServerGlobalVariables();
18551850
if (rows.Length == 0)
18561851
{
18571852
TaskCompletionSource<object> source = new TaskCompletionSource<object>();
@@ -1872,7 +1867,6 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok
18721867
_rowStateToSkip = DataRowState.Deleted; // Don't allow deleted rows
18731868
_rowSource = rows;
18741869
_dataTableSource = table;
1875-
_sqlDataReaderRowSource = null;
18761870
_rowSourceType = ValueSourceType.RowArray;
18771871
_rowEnumerator = rows.GetEnumerator();
18781872
_isAsyncBulkCopy = true;
@@ -1908,10 +1902,10 @@ public Task WriteToServerAsync(DbDataReader reader, CancellationToken cancellati
19081902
try
19091903
{
19101904
statistics = SqlStatistics.StartTimer(Statistics);
1905+
ResetWriteToServerGlobalVariables();
19111906
_rowSource = reader;
19121907
_sqlDataReaderRowSource = reader as SqlDataReader;
19131908
_dbDataReaderRowSource = reader;
1914-
_dataTableSource = null;
19151909
_rowSourceType = ValueSourceType.DbDataReader;
19161910
_isAsyncBulkCopy = true;
19171911
resultTask = WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken); // It returns Task since _isAsyncBulkCopy = true;
@@ -1946,10 +1940,10 @@ public Task WriteToServerAsync(IDataReader reader, CancellationToken cancellatio
19461940
try
19471941
{
19481942
statistics = SqlStatistics.StartTimer(Statistics);
1943+
ResetWriteToServerGlobalVariables();
19491944
_rowSource = reader;
19501945
_sqlDataReaderRowSource = _rowSource as SqlDataReader;
19511946
_dbDataReaderRowSource = _rowSource as DbDataReader;
1952-
_dataTableSource = null;
19531947
_rowSourceType = ValueSourceType.IDataReader;
19541948
_isAsyncBulkCopy = true;
19551949
resultTask = WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken); // It returns Task since _isAsyncBulkCopy = true;
@@ -1990,9 +1984,9 @@ public Task WriteToServerAsync(DataTable table, DataRowState rowState, Cancellat
19901984
try
19911985
{
19921986
statistics = SqlStatistics.StartTimer(Statistics);
1987+
ResetWriteToServerGlobalVariables();
19931988
_rowStateToSkip = ((rowState == 0) || (rowState == DataRowState.Deleted)) ? DataRowState.Deleted : ~rowState | DataRowState.Deleted;
19941989
_rowSource = table;
1995-
_sqlDataReaderRowSource = null;
19961990
_dataTableSource = table;
19971991
_rowSourceType = ValueSourceType.DataTable;
19981992
_rowEnumerator = table.Rows.GetEnumerator();
@@ -3212,5 +3206,17 @@ private Task WriteToServerInternalAsync(CancellationToken ctoken)
32123206
}
32133207
return resultTask;
32143208
}
3209+
3210+
private void ResetWriteToServerGlobalVariables()
3211+
{
3212+
_dataTableSource = null;
3213+
_dbDataReaderRowSource = null;
3214+
_isAsyncBulkCopy = false;
3215+
_rowEnumerator = null;
3216+
_rowSource = null;
3217+
_rowSourceType = ValueSourceType.Unspecified;
3218+
_sqlDataReaderRowSource = null;
3219+
_sqlDataReaderRowSource = null;
3220+
}
32153221
}
32163222
}

src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@
163163
<Compile Include="SQL\SqlBulkCopyTest\TableLock.cs" />
164164
<Compile Include="SQL\SqlBulkCopyTest\DataConversionErrorMessageTest.cs" />
165165
<Compile Include="SQL\SqlBulkCopyTest\CopyWidenNullInexactNumerics.cs" />
166+
<Compile Include="SQL\SqlBulkCopyTest\WriteToServerTest.cs" />
166167
</ItemGroup>
167168
<ItemGroup Condition="'$(TargetsWindows)' == 'true' AND ('$(TestSet)' == '' OR '$(TestSet)' == '2')">
168169
<Compile Include="SQL\SqlDSEnumeratorTest\SqlDataSourceEnumeratorTest.cs" />

0 commit comments

Comments
 (0)