44
55using System ;
66using System . Data ;
7- using System . Text ;
7+ using System . Threading . Tasks ;
88using Xunit ;
99
1010namespace Microsoft . Data . SqlClient . ManualTesting . Tests
1111{
12- public class TestBulkCopyWithUtf8
12+ public sealed class TestBulkCopyWithUtf8 : IDisposable
1313 {
14- private readonly string _connectionString ;
14+ private static string sourceTable = DataTestUtility . GetUniqueName ( "SrcUtf8DataTable" ) ;
15+ private static string destinationTable = DataTestUtility . GetUniqueName ( "DstUtf8DataTable" ) ;
16+ private static readonly string insertQuery = $ "INSERT INTO { sourceTable } VALUES('test')";
1517
1618 public TestBulkCopyWithUtf8 ( )
1719 {
18- _connectionString = new SqlConnectionStringBuilder ( DataTestUtility . TCPConnectionString ) { MultipleActiveResultSets = true } . ConnectionString ;
20+ using SqlConnection sourceConnection = new SqlConnection ( GetConnectionString ( true ) ) ;
21+ sourceConnection . Open ( ) ;
22+ SetupTables ( sourceConnection , sourceTable , destinationTable , insertQuery ) ;
23+ }
24+
25+ private string GetConnectionString ( bool enableMars )
26+ {
27+ return new SqlConnectionStringBuilder ( DataTestUtility . TCPConnectionString )
28+ {
29+ MultipleActiveResultSets = enableMars
30+ } . ConnectionString ;
1931 }
2032
2133 private void SetupTables ( SqlConnection connection , string sourceTable , string destinationTable , string insertQuery )
2234 {
2335 string columnDefinition = "(str_col varchar(max) COLLATE Latin1_General_100_CS_AS_KS_WS_SC_UTF8)" ;
2436 DataTestUtility . CreateTable ( connection , sourceTable , columnDefinition ) ;
2537 DataTestUtility . CreateTable ( connection , destinationTable , columnDefinition ) ;
26-
2738 using SqlCommand insertCommand = connection . CreateCommand ( ) ;
2839 insertCommand . CommandText = insertQuery ;
2940 Helpers . TryExecute ( insertCommand , insertQuery ) ;
3041 }
3142
32- [ ConditionalFact ( typeof ( DataTestUtility ) , nameof ( DataTestUtility . AreConnStringsSetup ) , nameof ( DataTestUtility . IsNotAzureServer ) , nameof ( DataTestUtility . IsNotAzureSynapse ) ) ]
33- public void BulkCopy_Utf8Data_ShouldMatchSource ( )
43+ [ ConditionalTheory ( typeof ( DataTestUtility ) ,
44+ nameof ( DataTestUtility . AreConnStringsSetup ) ,
45+ nameof ( DataTestUtility . IsNotAzureServer ) ,
46+ nameof ( DataTestUtility . IsNotAzureSynapse ) ) ]
47+ [ InlineData ( true , true ) ]
48+ [ InlineData ( false , true ) ]
49+ [ InlineData ( true , false ) ]
50+ [ InlineData ( false , false ) ]
51+ public void BulkCopy_Utf8Data_ShouldMatchSource ( bool isMarsEnabled , bool enableStreaming )
3452 {
35- string sourceTable = DataTestUtility . GetUniqueName ( "SrcUtf8DataTable" ) ;
36- string destinationTable = DataTestUtility . GetUniqueName ( "DstUtf8DataTable" ) ;
37- string insertQuery = $ "INSERT INTO { sourceTable } VALUES('test')";
38-
39- using SqlConnection sourceConnection = new SqlConnection ( _connectionString ) ;
53+ using SqlConnection sourceConnection = new SqlConnection ( GetConnectionString ( isMarsEnabled ) ) ;
4054 sourceConnection . Open ( ) ;
41- SetupTables ( sourceConnection , sourceTable , destinationTable , insertQuery ) ;
42-
4355 using SqlCommand countCommand = new SqlCommand ( $ "SELECT COUNT(*) FROM { destinationTable } ", sourceConnection ) ;
4456 long initialCount = Convert . ToInt64 ( countCommand . ExecuteScalar ( ) ) ;
45-
4657 using SqlCommand sourceDataCommand = new SqlCommand ( $ "SELECT str_col FROM { sourceTable } ", sourceConnection ) ;
4758 using SqlDataReader reader = sourceDataCommand . ExecuteReader ( CommandBehavior . SequentialAccess ) ;
48-
49- using SqlConnection destinationConnection = new SqlConnection ( _connectionString ) ;
59+ using SqlConnection destinationConnection = new SqlConnection ( GetConnectionString ( isMarsEnabled ) ) ;
5060 destinationConnection . Open ( ) ;
51-
61+
5262 using SqlBulkCopy bulkCopy = new SqlBulkCopy ( destinationConnection )
5363 {
54- EnableStreaming = true ,
64+ EnableStreaming = enableStreaming ,
5565 DestinationTableName = destinationTable
5666 } ;
5767
@@ -63,20 +73,74 @@ public void BulkCopy_Utf8Data_ShouldMatchSource()
6373 {
6474 Assert . Fail ( $ "Bulk copy failed: { ex . Message } ") ;
6575 }
66-
76+
77+ reader . Close ( ) ;
6778 long finalCount = Convert . ToInt64 ( countCommand . ExecuteScalar ( ) ) ;
6879 Assert . Equal ( 1 , finalCount - initialCount ) ;
69-
7080 using SqlCommand verifyCommand = new SqlCommand ( $ "SELECT cast(str_col as varbinary) FROM { destinationTable } ", destinationConnection ) ;
7181 using SqlDataReader verifyReader = verifyCommand . ExecuteReader ( CommandBehavior . SequentialAccess ) ;
72-
7382 byte [ ] expectedBytes = new byte [ ] { 0x74 , 0x65 , 0x73 , 0x74 } ;
74-
7583 Assert . True ( verifyReader . Read ( ) , "No data found in destination table after bulk copy." ) ;
84+ byte [ ] actualBytes = verifyReader . GetSqlBinary ( 0 ) . Value ;
85+ Assert . Equal ( expectedBytes . Length , actualBytes . Length ) ;
86+ Assert . Equal ( expectedBytes , actualBytes ) ;
87+ }
7688
89+
90+ [ ConditionalTheory ( typeof ( DataTestUtility ) ,
91+ nameof ( DataTestUtility . AreConnStringsSetup ) ,
92+ nameof ( DataTestUtility . IsNotAzureServer ) ,
93+ nameof ( DataTestUtility . IsNotAzureSynapse ) ) ]
94+ [ InlineData ( true , true ) ]
95+ [ InlineData ( false , true ) ]
96+ [ InlineData ( true , false ) ]
97+ [ InlineData ( false , false ) ]
98+ public async Task BulkCopy_Utf8Data_ShouldMatchSource_Async ( bool isMarsEnabled , bool enableStreaming )
99+ {
100+ string connectionString = GetConnectionString ( isMarsEnabled ) ;
101+ using SqlConnection sourceConnection = new SqlConnection ( connectionString ) ;
102+ await sourceConnection . OpenAsync ( ) ;
103+ using SqlCommand countCommand = new SqlCommand ( $ "SELECT COUNT(*) FROM { destinationTable } ", sourceConnection ) ;
104+ long initialCount = Convert . ToInt64 ( await countCommand . ExecuteScalarAsync ( ) ) ;
105+ using SqlCommand sourceDataCommand = new SqlCommand ( $ "SELECT str_col FROM { sourceTable } ", sourceConnection ) ;
106+ using SqlDataReader reader = await sourceDataCommand . ExecuteReaderAsync ( CommandBehavior . SequentialAccess ) ;
107+ using SqlConnection destinationConnection = new SqlConnection ( connectionString ) ;
108+ await destinationConnection . OpenAsync ( ) ;
109+
110+ using SqlBulkCopy bulkCopy = new SqlBulkCopy ( destinationConnection )
111+ {
112+ EnableStreaming = enableStreaming ,
113+ DestinationTableName = destinationTable
114+ } ;
115+
116+ try
117+ {
118+ await bulkCopy . WriteToServerAsync ( reader ) ;
119+ }
120+ catch ( Exception ex )
121+ {
122+ Assert . Fail ( $ "Bulk copy failed: { ex . Message } ") ;
123+ }
124+
125+ reader . Close ( ) ;
126+ long finalCount = Convert . ToInt64 ( await countCommand . ExecuteScalarAsync ( ) ) ;
127+ Assert . Equal ( 1 , finalCount - initialCount ) ;
128+ using SqlCommand verifyCommand = new SqlCommand ( $ "SELECT cast(str_col as varbinary) FROM { destinationTable } ", destinationConnection ) ;
129+ using SqlDataReader verifyReader = await verifyCommand . ExecuteReaderAsync ( CommandBehavior . SequentialAccess ) ;
130+ byte [ ] expectedBytes = new byte [ ] { 0x74 , 0x65 , 0x73 , 0x74 } ;
131+ Assert . True ( await verifyReader . ReadAsync ( ) , "No data found in destination table after bulk copy." ) ;
77132 byte [ ] actualBytes = verifyReader . GetSqlBinary ( 0 ) . Value ;
78133 Assert . Equal ( expectedBytes . Length , actualBytes . Length ) ;
79134 Assert . Equal ( expectedBytes , actualBytes ) ;
80135 }
136+
137+ public void Dispose ( )
138+ {
139+ using SqlConnection connection = new SqlConnection ( GetConnectionString ( true ) ) ;
140+ connection . Open ( ) ;
141+ DataTestUtility . DropTable ( connection , sourceTable ) ;
142+ DataTestUtility . DropTable ( connection , destinationTable ) ;
143+ connection . Close ( ) ;
144+ }
81145 }
82146}
0 commit comments