From f9ebb5a1ec691d3f57e4ca571932624888e1ab1b Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Tue, 27 Feb 2024 16:17:19 -0800 Subject: [PATCH 01/11] Added a method for resetting of global variables used by SqlBulkCopy.WriteToServer/WriteToServerAsync. --- .../Microsoft/Data/SqlClient/SqlBulkCopy.cs | 35 ++-- .../Microsoft/Data/SqlClient/SqlBulkCopy.cs | 34 ++-- ....Data.SqlClient.ManualTesting.Tests.csproj | 1 + .../SQL/SqlBulkCopyTest/WriteToServerTest.cs | 192 ++++++++++++++++++ 4 files changed, 233 insertions(+), 29 deletions(-) create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs index 273394395a..92c6d0075c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs @@ -1640,14 +1640,12 @@ public void WriteToServer(DbDataReader reader) try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _dbDataReaderRowSource = reader; _sqlDataReaderRowSource = reader as SqlDataReader; - - _dataTableSource = null; _rowSourceType = ValueSourceType.DbDataReader; - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(reader.FieldCount, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } finally @@ -1673,12 +1671,11 @@ public void WriteToServer(IDataReader reader) try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _sqlDataReaderRowSource = _rowSource as SqlDataReader; _dbDataReaderRowSource = _rowSource as DbDataReader; - _dataTableSource = null; _rowSourceType = ValueSourceType.IDataReader; - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(reader.FieldCount, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } finally @@ -1707,13 +1704,12 @@ public void WriteToServer(DataTable table, DataRowState rowState) try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowStateToSkip = ((rowState == 0) || (rowState == DataRowState.Deleted)) ? DataRowState.Deleted : ~rowState | DataRowState.Deleted; _rowSource = table; _dataTableSource = table; - _sqlDataReaderRowSource = null; _rowSourceType = ValueSourceType.DataTable; _rowEnumerator = table.Rows.GetEnumerator(); - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(table.Columns.Count, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } @@ -1746,16 +1742,14 @@ public void WriteToServer(DataRow[] rows) try { statistics = SqlStatistics.StartTimer(Statistics); - + ResetWriteToServerGlobalVariables(); DataTable table = rows[0].Table; Debug.Assert(null != table, "How can we have rows without a table?"); _rowStateToSkip = DataRowState.Deleted; // Don't allow deleted rows _rowSource = rows; _dataTableSource = table; - _sqlDataReaderRowSource = null; _rowSourceType = ValueSourceType.RowArray; _rowEnumerator = rows.GetEnumerator(); - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(table.Columns.Count, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } @@ -1787,7 +1781,7 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok try { statistics = SqlStatistics.StartTimer(Statistics); - + ResetWriteToServerGlobalVariables(); if (rows.Length == 0) { return cancellationToken.IsCancellationRequested ? @@ -1800,7 +1794,6 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok _rowStateToSkip = DataRowState.Deleted; // Don't allow deleted rows _rowSource = rows; _dataTableSource = table; - _sqlDataReaderRowSource = null; _rowSourceType = ValueSourceType.RowArray; _rowEnumerator = rows.GetEnumerator(); _isAsyncBulkCopy = true; @@ -1834,10 +1827,10 @@ public Task WriteToServerAsync(DbDataReader reader, CancellationToken cancellati try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _sqlDataReaderRowSource = reader as SqlDataReader; _dbDataReaderRowSource = reader; - _dataTableSource = null; _rowSourceType = ValueSourceType.DbDataReader; _isAsyncBulkCopy = true; resultTask = WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken); // It returns Task since _isAsyncBulkCopy = true; @@ -1871,10 +1864,10 @@ public Task WriteToServerAsync(IDataReader reader, CancellationToken cancellatio try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _sqlDataReaderRowSource = _rowSource as SqlDataReader; _dbDataReaderRowSource = _rowSource as DbDataReader; - _dataTableSource = null; _rowSourceType = ValueSourceType.IDataReader; _isAsyncBulkCopy = true; resultTask = WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken); // It returns Task since _isAsyncBulkCopy = true; @@ -1914,9 +1907,9 @@ public Task WriteToServerAsync(DataTable table, DataRowState rowState, Cancellat try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowStateToSkip = ((rowState == 0) || (rowState == DataRowState.Deleted)) ? DataRowState.Deleted : ~rowState | DataRowState.Deleted; _rowSource = table; - _sqlDataReaderRowSource = null; _dataTableSource = table; _rowSourceType = ValueSourceType.DataTable; _rowEnumerator = table.Rows.GetEnumerator(); @@ -3093,5 +3086,17 @@ private Task WriteToServerInternalAsync(CancellationToken ctoken) } return resultTask; } + + private void ResetWriteToServerGlobalVariables() + { + _dataTableSource = null; + _dbDataReaderRowSource = null; + _isAsyncBulkCopy = false; + _rowEnumerator = null; + _rowSource = null; + _rowSourceType = ValueSourceType.Unspecified; + _sqlDataReaderRowSource = null; + _sqlDataReaderRowSource = null; + } } } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs index 6b65491499..54b03683b7 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs @@ -1689,6 +1689,7 @@ public void WriteToServer(DbDataReader reader) try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _dbDataReaderRowSource = reader; _sqlDataReaderRowSource = reader as SqlDataReader; @@ -1697,10 +1698,8 @@ public void WriteToServer(DbDataReader reader) { _rowSourceIsSqlDataReaderSmi = _sqlDataReaderRowSource is SqlDataReaderSmi; } - _dataTableSource = null; _rowSourceType = ValueSourceType.DbDataReader; - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(reader.FieldCount, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } finally @@ -1728,6 +1727,7 @@ public void WriteToServer(IDataReader reader) try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _sqlDataReaderRowSource = _rowSource as SqlDataReader; if (_sqlDataReaderRowSource != null) @@ -1735,9 +1735,7 @@ public void WriteToServer(IDataReader reader) _rowSourceIsSqlDataReaderSmi = _sqlDataReaderRowSource is SqlDataReaderSmi; } _dbDataReaderRowSource = _rowSource as DbDataReader; - _dataTableSource = null; _rowSourceType = ValueSourceType.IDataReader; - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(reader.FieldCount, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } finally @@ -1768,13 +1766,12 @@ public void WriteToServer(DataTable table, DataRowState rowState) try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowStateToSkip = ((rowState == 0) || (rowState == DataRowState.Deleted)) ? DataRowState.Deleted : ~rowState | DataRowState.Deleted; _rowSource = table; _dataTableSource = table; - _sqlDataReaderRowSource = null; _rowSourceType = ValueSourceType.DataTable; _rowEnumerator = table.Rows.GetEnumerator(); - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(table.Columns.Count, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } @@ -1809,16 +1806,14 @@ public void WriteToServer(DataRow[] rows) try { statistics = SqlStatistics.StartTimer(Statistics); - + ResetWriteToServerGlobalVariables(); DataTable table = rows[0].Table; Debug.Assert(null != table, "How can we have rows without a table?"); _rowStateToSkip = DataRowState.Deleted; // Don't allow deleted rows _rowSource = rows; _dataTableSource = table; - _sqlDataReaderRowSource = null; _rowSourceType = ValueSourceType.RowArray; _rowEnumerator = rows.GetEnumerator(); - _isAsyncBulkCopy = false; WriteRowSourceToServerAsync(table.Columns.Count, CancellationToken.None); //It returns null since _isAsyncBulkCopy = false; } @@ -1851,7 +1846,7 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok try { statistics = SqlStatistics.StartTimer(Statistics); - + ResetWriteToServerGlobalVariables(); if (rows.Length == 0) { TaskCompletionSource source = new TaskCompletionSource(); @@ -1872,7 +1867,6 @@ public Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationTok _rowStateToSkip = DataRowState.Deleted; // Don't allow deleted rows _rowSource = rows; _dataTableSource = table; - _sqlDataReaderRowSource = null; _rowSourceType = ValueSourceType.RowArray; _rowEnumerator = rows.GetEnumerator(); _isAsyncBulkCopy = true; @@ -1908,10 +1902,10 @@ public Task WriteToServerAsync(DbDataReader reader, CancellationToken cancellati try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _sqlDataReaderRowSource = reader as SqlDataReader; _dbDataReaderRowSource = reader; - _dataTableSource = null; _rowSourceType = ValueSourceType.DbDataReader; _isAsyncBulkCopy = true; resultTask = WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken); // It returns Task since _isAsyncBulkCopy = true; @@ -1946,10 +1940,10 @@ public Task WriteToServerAsync(IDataReader reader, CancellationToken cancellatio try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowSource = reader; _sqlDataReaderRowSource = _rowSource as SqlDataReader; _dbDataReaderRowSource = _rowSource as DbDataReader; - _dataTableSource = null; _rowSourceType = ValueSourceType.IDataReader; _isAsyncBulkCopy = true; resultTask = WriteRowSourceToServerAsync(reader.FieldCount, cancellationToken); // It returns Task since _isAsyncBulkCopy = true; @@ -1990,9 +1984,9 @@ public Task WriteToServerAsync(DataTable table, DataRowState rowState, Cancellat try { statistics = SqlStatistics.StartTimer(Statistics); + ResetWriteToServerGlobalVariables(); _rowStateToSkip = ((rowState == 0) || (rowState == DataRowState.Deleted)) ? DataRowState.Deleted : ~rowState | DataRowState.Deleted; _rowSource = table; - _sqlDataReaderRowSource = null; _dataTableSource = table; _rowSourceType = ValueSourceType.DataTable; _rowEnumerator = table.Rows.GetEnumerator(); @@ -3212,5 +3206,17 @@ private Task WriteToServerInternalAsync(CancellationToken ctoken) } return resultTask; } + + private void ResetWriteToServerGlobalVariables() + { + _dataTableSource = null; + _dbDataReaderRowSource = null; + _isAsyncBulkCopy = false; + _rowEnumerator = null; + _rowSource = null; + _rowSourceType = ValueSourceType.Unspecified; + _sqlDataReaderRowSource = null; + _sqlDataReaderRowSource = null; + } } } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj index da3f55dfc1..9644bdc43d 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj @@ -284,6 +284,7 @@ + diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs new file mode 100644 index 0000000000..af29612f69 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs @@ -0,0 +1,192 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Data; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Data.SqlClient.ManualTesting.Tests.SQL.SqlBulkCopyTest +{ + public class WriteToServerTest + { + private string _connectionString = null; + + public WriteToServerTest() + { + _connectionString = (new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true }).ConnectionString; + } + + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer))] + public async Task WriteToServerWithDbReaderFollowedByWriteToServerWithDataRowsShouldSucceed() + { + try + { + SetupTestTables(); + + DataRow[] dataRows = CreateDataRows(); + + bool result = DoBulkCopy(dataRows); + Assert.True(result, "WriteToServer with IDataReader followed by WriteToServer with data rows test failed."); + Assert.True(GetCopiedRecordsCount() == 8, "WriteToServer with IDataReader followed by WriteToServer with data rows test failed."); + + CleanupTestTable2(); + + result = await DoBulkCopyAsync(dataRows); + Assert.True(result, "WriteToServerAsync with IDataReader followed by WriteToServerAsync with data rows test failed."); + Assert.True(GetCopiedRecordsCount() == 8, "WriteToServerAsync with IDataReader followed by WriteToServerAsync with data rows test failed."); + } + finally + { + RemoveTestTables(); + } + } + + private DataRow[] CreateDataRows() + { + DataTable table = new DataTable(); + table.Columns.Add("Id", typeof(int)); + table.Columns.Add("FirstName", typeof(string)); + table.Columns.Add("LastName", typeof(string)); + + table.Rows.Add(null, "Aaron", "Washington"); + table.Rows.Add(null, "Barry", "Mannilow"); + table.Rows.Add(null, "Charles", "Babage"); + table.Rows.Add(null, "Dean", "Snipes"); + + return table.Select(); + } + + private int GetCopiedRecordsCount() + { + using (SqlConnection connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + using (SqlCommand command = new SqlCommand("select count(*) from TestTable2", connection)) + { + return (int)command.ExecuteScalar(); + } + } + } + + private void CleanupTestTable2() + { + using (SqlConnection connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + SqlCommand command = connection.CreateCommand(); + + Helpers.TryExecute(command, "delete from TestTable2"); + } + } + + private void SetupTestTables() + { + using (SqlConnection connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + SqlCommand command = connection.CreateCommand(); + + Helpers.TryExecute(command, "drop table if exists TestTable1"); + Helpers.TryExecute(command, "drop table if exists TestTable2"); + + Helpers.TryExecute(command, "create table TestTable1 (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); + Helpers.TryExecute(command, "create table TestTable2 (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); + + Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('John', 'Doe')"); + Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Johnny', 'Smith')"); + Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Jenny', 'Doe')"); + Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Jane', 'Smith')"); + } + } + + private void RemoveTestTables() + { + using (SqlConnection connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + SqlCommand command = connection.CreateCommand(); + + Helpers.TryExecute(command, "drop table if exists TestTable1"); + Helpers.TryExecute(command, "drop table if exists TestTable2"); + } + } + + private bool DoBulkCopy(DataRow[] dataRows) + { + using (SqlConnection connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + string sql = "select * from TestTable1"; + SqlCommand command = new SqlCommand(sql, connection); + IDataReader reader = command.ExecuteReader(); + SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); + bulkCopy.DestinationTableName = "TestTable2"; + + return BulkCopy(bulkCopy, reader, dataRows); + } + } + + private async Task DoBulkCopyAsync(DataRow[] dataRows) + { + using (SqlConnection connection = new SqlConnection(_connectionString)) + { + await connection.OpenAsync(); + + SqlCommand command = connection.CreateCommand(); + + string sql = "select * from TestTable1"; + command = new SqlCommand(sql, connection); + IDataReader reader = await command.ExecuteReaderAsync(); + SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); + bulkCopy.DestinationTableName = "TestTable2"; + + return await BulkCopyAsync(bulkCopy, reader, dataRows); + } + } + + private bool BulkCopy(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRows) + { + try + { + using (reader) + { + bulkCopy.WriteToServer(reader); + } + + bulkCopy.WriteToServer(dataRows); + + return true; + } + catch (Exception) + { + return false; + } + } + + private async Task BulkCopyAsync(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRows) + { + try + { + using (reader) + { + await bulkCopy.WriteToServerAsync(reader); + } + + await bulkCopy.WriteToServerAsync(dataRows); + + return true; + } + catch (Exception) + { + return false; + } + } + } +} From 77a79dd6ec1f1583bd5eee4525f3377bff95ddf8 Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Tue, 27 Feb 2024 16:37:02 -0800 Subject: [PATCH 02/11] Added WriteToServer.cs to ManualTest project file. --- .../Microsoft.Data.SqlClient.ManualTesting.Tests.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj index 9644bdc43d..f759ccfac9 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj @@ -163,6 +163,7 @@ + From 233443acc4335b875e5b81340d2372b47b363a6c Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Tue, 27 Feb 2024 16:41:22 -0800 Subject: [PATCH 03/11] Fixed WriteToServerTest namespace. --- .../tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs index af29612f69..ee16cc0248 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests.SQL.SqlBulkCopyTest +namespace Microsoft.Data.SqlClient.ManualTesting.Tests { public class WriteToServerTest { From e73be1ea7c28bbea2d10e0a274098fb980f3b6e6 Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Tue, 27 Feb 2024 17:28:46 -0800 Subject: [PATCH 04/11] Fixed Manual Test project file for duplicate entry or WriteToServerTest.cs. --- .../Microsoft.Data.SqlClient.ManualTesting.Tests.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj index f759ccfac9..728d379f6a 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj @@ -285,7 +285,6 @@ - From 951d85c6e5168fe905fd7669049734e16e18b02a Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Wed, 28 Feb 2024 10:13:13 -0800 Subject: [PATCH 05/11] Added disposition of objects no longer required. --- .../SQL/SqlBulkCopyTest/WriteToServerTest.cs | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs index ee16cc0248..8378cb9b2b 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs @@ -80,6 +80,8 @@ private void CleanupTestTable2() SqlCommand command = connection.CreateCommand(); Helpers.TryExecute(command, "delete from TestTable2"); + + command.Dispose(); } } @@ -101,6 +103,8 @@ private void SetupTestTables() Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Johnny', 'Smith')"); Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Jenny', 'Doe')"); Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Jane', 'Smith')"); + + command.Dispose(); } } @@ -114,6 +118,8 @@ private void RemoveTestTables() Helpers.TryExecute(command, "drop table if exists TestTable1"); Helpers.TryExecute(command, "drop table if exists TestTable2"); + + command.Dispose(); } } @@ -129,7 +135,12 @@ private bool DoBulkCopy(DataRow[] dataRows) SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); bulkCopy.DestinationTableName = "TestTable2"; - return BulkCopy(bulkCopy, reader, dataRows); + bool result = BulkCopy(bulkCopy, reader, dataRows); + + reader.Close(); + command.Dispose(); + + return result; } } @@ -147,7 +158,12 @@ private async Task DoBulkCopyAsync(DataRow[] dataRows) SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); bulkCopy.DestinationTableName = "TestTable2"; - return await BulkCopyAsync(bulkCopy, reader, dataRows); + bool result = await BulkCopyAsync(bulkCopy, reader, dataRows); + + reader.Close(); + command.Dispose(); + + return result; } } @@ -155,11 +171,7 @@ private bool BulkCopy(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRo { try { - using (reader) - { - bulkCopy.WriteToServer(reader); - } - + bulkCopy.WriteToServer(reader); bulkCopy.WriteToServer(dataRows); return true; @@ -174,11 +186,7 @@ private async Task BulkCopyAsync(SqlBulkCopy bulkCopy, IDataReader reader, { try { - using (reader) - { - await bulkCopy.WriteToServerAsync(reader); - } - + await bulkCopy.WriteToServerAsync(reader); await bulkCopy.WriteToServerAsync(dataRows); return true; From 72982c7edd19f19f4396a32dda13a9a76295da10 Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Wed, 28 Feb 2024 10:18:38 -0800 Subject: [PATCH 06/11] Reorder methods location. --- .../SQL/SqlBulkCopyTest/WriteToServerTest.cs | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs index 8378cb9b2b..09adf2df77 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs @@ -43,6 +43,29 @@ public async Task WriteToServerWithDbReaderFollowedByWriteToServerWithDataRowsSh } } + private void SetupTestTables() + { + using (SqlConnection connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + SqlCommand command = connection.CreateCommand(); + + Helpers.TryExecute(command, "drop table if exists TestTable1"); + Helpers.TryExecute(command, "drop table if exists TestTable2"); + + Helpers.TryExecute(command, "create table TestTable1 (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); + Helpers.TryExecute(command, "create table TestTable2 (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); + + Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('John', 'Doe')"); + Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Johnny', 'Smith')"); + Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Jenny', 'Doe')"); + Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Jane', 'Smith')"); + + command.Dispose(); + } + } + private DataRow[] CreateDataRows() { DataTable table = new DataTable(); @@ -85,29 +108,6 @@ private void CleanupTestTable2() } } - private void SetupTestTables() - { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - connection.Open(); - - SqlCommand command = connection.CreateCommand(); - - Helpers.TryExecute(command, "drop table if exists TestTable1"); - Helpers.TryExecute(command, "drop table if exists TestTable2"); - - Helpers.TryExecute(command, "create table TestTable1 (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); - Helpers.TryExecute(command, "create table TestTable2 (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); - - Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('John', 'Doe')"); - Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Johnny', 'Smith')"); - Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Jenny', 'Doe')"); - Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Jane', 'Smith')"); - - command.Dispose(); - } - } - private void RemoveTestTables() { using (SqlConnection connection = new SqlConnection(_connectionString)) From 9c9a820a75b2437d16eafb9120b542e85be1b6cf Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Wed, 28 Feb 2024 16:54:45 -0800 Subject: [PATCH 07/11] Added class level table name variables and generate unique values. --- .../SQL/SqlBulkCopyTest/WriteToServerTest.cs | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs index 09adf2df77..c0ce2ea851 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs @@ -12,6 +12,8 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests public class WriteToServerTest { private string _connectionString = null; + private string _tableName1 = DataTestUtility.GetUniqueName("Bulk1"); + private string _tableName2 = DataTestUtility.GetUniqueName("Bulk2"); public WriteToServerTest() { @@ -51,16 +53,16 @@ private void SetupTestTables() SqlCommand command = connection.CreateCommand(); - Helpers.TryExecute(command, "drop table if exists TestTable1"); - Helpers.TryExecute(command, "drop table if exists TestTable2"); + Helpers.TryExecute(command, $"drop table if exists {_tableName1}"); + Helpers.TryExecute(command, $"drop table if exists {_tableName2}"); - Helpers.TryExecute(command, "create table TestTable1 (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); - Helpers.TryExecute(command, "create table TestTable2 (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); + Helpers.TryExecute(command, $"create table {_tableName1} (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); + Helpers.TryExecute(command, $"create table {_tableName2} (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); - Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('John', 'Doe')"); - Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Johnny', 'Smith')"); - Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Jenny', 'Doe')"); - Helpers.TryExecute(command, "insert into TestTable1 (Firstname, LastName) values ('Jane', 'Smith')"); + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('John', 'Doe')"); + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Johnny', 'Smith')"); + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Jenny', 'Doe')"); + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Jane', 'Smith')"); command.Dispose(); } @@ -87,7 +89,7 @@ private int GetCopiedRecordsCount() { connection.Open(); - using (SqlCommand command = new SqlCommand("select count(*) from TestTable2", connection)) + using (SqlCommand command = new SqlCommand($"select count(*) from {_tableName2}", connection)) { return (int)command.ExecuteScalar(); } @@ -102,7 +104,7 @@ private void CleanupTestTable2() SqlCommand command = connection.CreateCommand(); - Helpers.TryExecute(command, "delete from TestTable2"); + Helpers.TryExecute(command, $"delete from {_tableName2}"); command.Dispose(); } @@ -116,8 +118,8 @@ private void RemoveTestTables() SqlCommand command = connection.CreateCommand(); - Helpers.TryExecute(command, "drop table if exists TestTable1"); - Helpers.TryExecute(command, "drop table if exists TestTable2"); + Helpers.TryExecute(command, $"drop table if exists {_tableName1}"); + Helpers.TryExecute(command, $"drop table if exists {_tableName2}"); command.Dispose(); } @@ -129,11 +131,11 @@ private bool DoBulkCopy(DataRow[] dataRows) { connection.Open(); - string sql = "select * from TestTable1"; + string sql = $"select * from {_tableName1}"; SqlCommand command = new SqlCommand(sql, connection); IDataReader reader = command.ExecuteReader(); SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); - bulkCopy.DestinationTableName = "TestTable2"; + bulkCopy.DestinationTableName = $"{_tableName2}"; bool result = BulkCopy(bulkCopy, reader, dataRows); @@ -152,11 +154,11 @@ private async Task DoBulkCopyAsync(DataRow[] dataRows) SqlCommand command = connection.CreateCommand(); - string sql = "select * from TestTable1"; + string sql = $"select * from {_tableName1}"; command = new SqlCommand(sql, connection); IDataReader reader = await command.ExecuteReaderAsync(); SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); - bulkCopy.DestinationTableName = "TestTable2"; + bulkCopy.DestinationTableName = $"{_tableName2}"; bool result = await BulkCopyAsync(bulkCopy, reader, dataRows); From 0f7cfbcc92c911651d30ecffc4eec9bdd54f598f Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Wed, 28 Feb 2024 17:06:12 -0800 Subject: [PATCH 08/11] Remove string interpolation if nothing else is inside the string apart from the variable. --- .../ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs index c0ce2ea851..bb758ff4ab 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs @@ -135,7 +135,7 @@ private bool DoBulkCopy(DataRow[] dataRows) SqlCommand command = new SqlCommand(sql, connection); IDataReader reader = command.ExecuteReader(); SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); - bulkCopy.DestinationTableName = $"{_tableName2}"; + bulkCopy.DestinationTableName = _tableName2; bool result = BulkCopy(bulkCopy, reader, dataRows); @@ -158,7 +158,7 @@ private async Task DoBulkCopyAsync(DataRow[] dataRows) command = new SqlCommand(sql, connection); IDataReader reader = await command.ExecuteReaderAsync(); SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); - bulkCopy.DestinationTableName = $"{_tableName2}"; + bulkCopy.DestinationTableName = _tableName2; bool result = await BulkCopyAsync(bulkCopy, reader, dataRows); From 218d113461ef0d4787b8d103b7d6edd56bb208e9 Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Fri, 1 Mar 2024 10:47:04 -0800 Subject: [PATCH 09/11] Apply all suggestions from PR review comments. --- .../SQL/SqlBulkCopyTest/WriteToServerTest.cs | 118 ++++++++---------- 1 file changed, 55 insertions(+), 63 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs index bb758ff4ab..b5bb462e19 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs @@ -11,9 +11,10 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests { public class WriteToServerTest { - private string _connectionString = null; - private string _tableName1 = DataTestUtility.GetUniqueName("Bulk1"); - private string _tableName2 = DataTestUtility.GetUniqueName("Bulk2"); + private readonly string _connectionString = null; + private readonly string _tableName1 = DataTestUtility.GetUniqueName("Bulk1"); + private readonly string _tableName2 = DataTestUtility.GetUniqueName("Bulk2"); + private static int _copiedRecordCount; public WriteToServerTest() { @@ -27,17 +28,20 @@ public async Task WriteToServerWithDbReaderFollowedByWriteToServerWithDataRowsSh { SetupTestTables(); - DataRow[] dataRows = CreateDataRows(); + DataRow[] dataRows = WriteToServerTest.CreateDataRows(); + Assert.Equal(4, dataRows.Length); + _copiedRecordCount = 0; bool result = DoBulkCopy(dataRows); Assert.True(result, "WriteToServer with IDataReader followed by WriteToServer with data rows test failed."); - Assert.True(GetCopiedRecordsCount() == 8, "WriteToServer with IDataReader followed by WriteToServer with data rows test failed."); + Assert.Equal(8, _copiedRecordCount); CleanupTestTable2(); + _copiedRecordCount = 0; result = await DoBulkCopyAsync(dataRows); Assert.True(result, "WriteToServerAsync with IDataReader followed by WriteToServerAsync with data rows test failed."); - Assert.True(GetCopiedRecordsCount() == 8, "WriteToServerAsync with IDataReader followed by WriteToServerAsync with data rows test failed."); + Assert.Equal(8, _copiedRecordCount); } finally { @@ -51,24 +55,23 @@ private void SetupTestTables() { connection.Open(); - SqlCommand command = connection.CreateCommand(); - - Helpers.TryExecute(command, $"drop table if exists {_tableName1}"); - Helpers.TryExecute(command, $"drop table if exists {_tableName2}"); - - Helpers.TryExecute(command, $"create table {_tableName1} (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); - Helpers.TryExecute(command, $"create table {_tableName2} (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); + using (SqlCommand command = connection.CreateCommand()) + { + DataTestUtility.DropTable(connection, _tableName1); + DataTestUtility.DropTable(connection, _tableName2); - Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('John', 'Doe')"); - Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Johnny', 'Smith')"); - Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Jenny', 'Doe')"); - Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Jane', 'Smith')"); + Helpers.TryExecute(command, $"create table {_tableName1} (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); + Helpers.TryExecute(command, $"create table {_tableName2} (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); - command.Dispose(); + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('John', 'Doe')"); + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Johnny', 'Smith')"); + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Jenny', 'Doe')"); + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Jane', 'Smith')"); + } } } - private DataRow[] CreateDataRows() + private static DataRow[] CreateDataRows() { DataTable table = new DataTable(); table.Columns.Add("Id", typeof(int)); @@ -83,30 +86,17 @@ private DataRow[] CreateDataRows() return table.Select(); } - private int GetCopiedRecordsCount() + private void CleanupTestTable2() { using (SqlConnection connection = new SqlConnection(_connectionString)) { connection.Open(); - using (SqlCommand command = new SqlCommand($"select count(*) from {_tableName2}", connection)) + using (SqlCommand command = connection.CreateCommand()) { - return (int)command.ExecuteScalar(); + Helpers.TryExecute(command, $"delete from {_tableName2}"); } - } - } - - private void CleanupTestTable2() - { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - connection.Open(); - SqlCommand command = connection.CreateCommand(); - - Helpers.TryExecute(command, $"delete from {_tableName2}"); - - command.Dispose(); } } @@ -115,13 +105,9 @@ private void RemoveTestTables() using (SqlConnection connection = new SqlConnection(_connectionString)) { connection.Open(); - - SqlCommand command = connection.CreateCommand(); - - Helpers.TryExecute(command, $"drop table if exists {_tableName1}"); - Helpers.TryExecute(command, $"drop table if exists {_tableName2}"); - - command.Dispose(); + + DataTestUtility.DropTable(connection, _tableName1); + DataTestUtility.DropTable(connection, _tableName2); } } @@ -131,18 +117,20 @@ private bool DoBulkCopy(DataRow[] dataRows) { connection.Open(); - string sql = $"select * from {_tableName1}"; - SqlCommand command = new SqlCommand(sql, connection); - IDataReader reader = command.ExecuteReader(); - SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); - bulkCopy.DestinationTableName = _tableName2; + using (SqlCommand command = connection.CreateCommand()) + { + command.CommandText = $"select * from {_tableName1}"; + + using IDataReader reader = command.ExecuteReader(); + + using SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); - bool result = BulkCopy(bulkCopy, reader, dataRows); + bulkCopy.DestinationTableName = _tableName2; - reader.Close(); - command.Dispose(); + bool result = BulkCopy(bulkCopy, reader, dataRows); - return result; + return result; + } } } @@ -152,29 +140,31 @@ private async Task DoBulkCopyAsync(DataRow[] dataRows) { await connection.OpenAsync(); - SqlCommand command = connection.CreateCommand(); + using (SqlCommand command = connection.CreateCommand()) + { + command.CommandText = $"select * from {_tableName1}"; + + using IDataReader reader = await command.ExecuteReaderAsync(); - string sql = $"select * from {_tableName1}"; - command = new SqlCommand(sql, connection); - IDataReader reader = await command.ExecuteReaderAsync(); - SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); - bulkCopy.DestinationTableName = _tableName2; + using SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); - bool result = await BulkCopyAsync(bulkCopy, reader, dataRows); + bulkCopy.DestinationTableName = _tableName2; - reader.Close(); - command.Dispose(); + bool result = await BulkCopyAsync(bulkCopy, reader, dataRows); - return result; + return result; + } } } - private bool BulkCopy(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRows) + private static bool BulkCopy(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRows) { try { bulkCopy.WriteToServer(reader); + _copiedRecordCount = bulkCopy.RowsCopied; bulkCopy.WriteToServer(dataRows); + _copiedRecordCount += bulkCopy.RowsCopied; return true; } @@ -184,12 +174,14 @@ private bool BulkCopy(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRo } } - private async Task BulkCopyAsync(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRows) + private static async Task BulkCopyAsync(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRows) { try { await bulkCopy.WriteToServerAsync(reader); + _copiedRecordCount = bulkCopy.RowsCopied; await bulkCopy.WriteToServerAsync(dataRows); + _copiedRecordCount += bulkCopy.RowsCopied; return true; } From d88e60b02aa8d0033d501421a06c3ca304680f8a Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Fri, 1 Mar 2024 11:13:17 -0800 Subject: [PATCH 10/11] Removed a blank line after a using block. --- .../tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs index b5bb462e19..0e5cf1b658 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs @@ -96,7 +96,6 @@ private void CleanupTestTable2() { Helpers.TryExecute(command, $"delete from {_tableName2}"); } - } } From 209a20aa6c4788f527acd663e6ea719013fcdc00 Mon Sep 17 00:00:00 2001 From: Davoud Date: Mon, 4 Mar 2024 13:08:26 -0800 Subject: [PATCH 11/11] test improvement --- .../SQL/SqlBulkCopyTest/WriteToServerTest.cs | 159 ++++++------------ 1 file changed, 52 insertions(+), 107 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs index 0e5cf1b658..343a7bcfe2 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/WriteToServerTest.cs @@ -14,14 +14,13 @@ public class WriteToServerTest private readonly string _connectionString = null; private readonly string _tableName1 = DataTestUtility.GetUniqueName("Bulk1"); private readonly string _tableName2 = DataTestUtility.GetUniqueName("Bulk2"); - private static int _copiedRecordCount; public WriteToServerTest() { _connectionString = (new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true }).ConnectionString; } - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer))] + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer), nameof(DataTestUtility.IsNotAzureSynapse))] public async Task WriteToServerWithDbReaderFollowedByWriteToServerWithDataRowsShouldSucceed() { try @@ -29,19 +28,10 @@ public async Task WriteToServerWithDbReaderFollowedByWriteToServerWithDataRowsSh SetupTestTables(); DataRow[] dataRows = WriteToServerTest.CreateDataRows(); - Assert.Equal(4, dataRows.Length); + Assert.Equal(4, dataRows.Length); // Verify the number of rows created - _copiedRecordCount = 0; - bool result = DoBulkCopy(dataRows); - Assert.True(result, "WriteToServer with IDataReader followed by WriteToServer with data rows test failed."); - Assert.Equal(8, _copiedRecordCount); - - CleanupTestTable2(); - - _copiedRecordCount = 0; - result = await DoBulkCopyAsync(dataRows); - Assert.True(result, "WriteToServerAsync with IDataReader followed by WriteToServerAsync with data rows test failed."); - Assert.Equal(8, _copiedRecordCount); + DoBulkCopy(dataRows); + await DoBulkCopyAsync(dataRows); } finally { @@ -51,24 +41,22 @@ public async Task WriteToServerWithDbReaderFollowedByWriteToServerWithDataRowsSh private void SetupTestTables() { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - connection.Open(); + // Create the source table and insert some data + using SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString); + connection.Open(); - using (SqlCommand command = connection.CreateCommand()) - { - DataTestUtility.DropTable(connection, _tableName1); - DataTestUtility.DropTable(connection, _tableName2); + DataTestUtility.DropTable(connection, _tableName1); + DataTestUtility.DropTable(connection, _tableName2); - Helpers.TryExecute(command, $"create table {_tableName1} (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); - Helpers.TryExecute(command, $"create table {_tableName2} (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); + using SqlCommand command = connection.CreateCommand(); - Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('John', 'Doe')"); - Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Johnny', 'Smith')"); - Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Jenny', 'Doe')"); - Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Jane', 'Smith')"); - } - } + Helpers.TryExecute(command, $"create table {_tableName1} (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); + Helpers.TryExecute(command, $"create table {_tableName2} (Id int identity primary key, FirstName nvarchar(50), LastName nvarchar(50))"); + + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('John', 'Doe')"); + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Johnny', 'Smith')"); + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Jenny', 'Doe')"); + Helpers.TryExecute(command, $"insert into {_tableName1} (Firstname, LastName) values ('Jane', 'Smith')"); } private static DataRow[] CreateDataRows() @@ -86,108 +74,65 @@ private static DataRow[] CreateDataRows() return table.Select(); } - private void CleanupTestTable2() - { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - connection.Open(); - - using (SqlCommand command = connection.CreateCommand()) - { - Helpers.TryExecute(command, $"delete from {_tableName2}"); - } - } - } - private void RemoveTestTables() { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - connection.Open(); - - DataTestUtility.DropTable(connection, _tableName1); - DataTestUtility.DropTable(connection, _tableName2); - } + // Simplify the using statement in a small block of code + using SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString); + connection.Open(); + + DataTestUtility.DropTable(connection, _tableName1); + DataTestUtility.DropTable(connection, _tableName2); } - private bool DoBulkCopy(DataRow[] dataRows) + private void DoBulkCopy(DataRow[] dataRows) { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - connection.Open(); - - using (SqlCommand command = connection.CreateCommand()) - { - command.CommandText = $"select * from {_tableName1}"; + using SqlConnection connection = new SqlConnection(_connectionString); + connection.Open(); - using IDataReader reader = command.ExecuteReader(); + using SqlCommand command = connection.CreateCommand(); + command.CommandText = $"select * from {_tableName1}"; - using SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); + using IDataReader reader = command.ExecuteReader(); - bulkCopy.DestinationTableName = _tableName2; + using SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); - bool result = BulkCopy(bulkCopy, reader, dataRows); + bulkCopy.DestinationTableName = _tableName2; - return result; - } - } + BulkCopy(bulkCopy, reader, dataRows); } - private async Task DoBulkCopyAsync(DataRow[] dataRows) + private async Task DoBulkCopyAsync(DataRow[] dataRows) { - using (SqlConnection connection = new SqlConnection(_connectionString)) - { - await connection.OpenAsync(); + // Test should be run with MARS enabled + using SqlConnection connection = new SqlConnection(_connectionString); + await connection.OpenAsync(); - using (SqlCommand command = connection.CreateCommand()) - { - command.CommandText = $"select * from {_tableName1}"; + using SqlCommand command = connection.CreateCommand(); + command.CommandText = $"select * from {_tableName1}"; - using IDataReader reader = await command.ExecuteReaderAsync(); + using IDataReader reader = await command.ExecuteReaderAsync(); - using SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); + using SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); - bulkCopy.DestinationTableName = _tableName2; + bulkCopy.DestinationTableName = _tableName2; - bool result = await BulkCopyAsync(bulkCopy, reader, dataRows); - - return result; - } - } + await BulkCopyAsync(bulkCopy, reader, dataRows); } - private static bool BulkCopy(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRows) + private static void BulkCopy(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRows) { - try - { - bulkCopy.WriteToServer(reader); - _copiedRecordCount = bulkCopy.RowsCopied; - bulkCopy.WriteToServer(dataRows); - _copiedRecordCount += bulkCopy.RowsCopied; - - return true; - } - catch (Exception) - { - return false; - } + bulkCopy.WriteToServer(reader); + Assert.Equal(dataRows.Length, bulkCopy.RowsCopied); // Verify the number of rows copied from the reader + bulkCopy.WriteToServer(dataRows); + Assert.Equal(dataRows.Length, bulkCopy.RowsCopied); // Verify the number of rows copied from the reader } - private static async Task BulkCopyAsync(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRows) + private static async Task BulkCopyAsync(SqlBulkCopy bulkCopy, IDataReader reader, DataRow[] dataRows) { - try - { - await bulkCopy.WriteToServerAsync(reader); - _copiedRecordCount = bulkCopy.RowsCopied; - await bulkCopy.WriteToServerAsync(dataRows); - _copiedRecordCount += bulkCopy.RowsCopied; - - return true; - } - catch (Exception) - { - return false; - } + await bulkCopy.WriteToServerAsync(reader); + Assert.Equal(dataRows.Length, bulkCopy.RowsCopied); // Verify the number of rows copied from the reader + await bulkCopy.WriteToServerAsync(dataRows); + Assert.Equal(dataRows.Length, bulkCopy.RowsCopied); // Verify the number of rows copied from the reader } } }