1
1
using System ;
2
2
using System . Buffers ;
3
3
using System . Buffers . Text ;
4
+ using System . Collections . Generic ;
4
5
using System . Data ;
5
- using System . Data . Common ;
6
6
using System . Text ;
7
7
using System . Threading ;
8
8
using System . Threading . Tasks ;
9
9
using MySql . Data . Types ;
10
+ using MySqlConnector . Core ;
10
11
using MySqlConnector . Protocol ;
11
12
using MySqlConnector . Protocol . Serialization ;
12
13
using MySqlConnector . Utilities ;
@@ -26,39 +27,33 @@ public MySqlBulkCopy(MySqlConnection connection, MySqlTransaction? transaction =
26
27
public string ? DestinationTableName { get ; set ; }
27
28
28
29
#if ! NETSTANDARD1_3
29
- public void WriteToServer ( DataTable dataTable ) => WriteToServerAsync ( dataTable , IOBehavior . Synchronous , CancellationToken . None ) . GetAwaiter ( ) . GetResult ( ) ;
30
+ public void WriteToServer ( DataTable dataTable ) => WriteToServerAsync ( DataRowsValuesEnumerator . Create ( dataTable ) , IOBehavior . Synchronous , CancellationToken . None ) . GetAwaiter ( ) . GetResult ( ) ;
30
31
31
32
#if ! NETSTANDARD2_1 && ! NETCOREAPP3_0
32
- public Task WriteToServerAsync ( DataTable dataTable , CancellationToken cancellationToken = default ) => WriteToServerAsync ( dataTable , IOBehavior . Asynchronous , cancellationToken ) . AsTask ( ) ;
33
+ public Task WriteToServerAsync ( DataTable dataTable , CancellationToken cancellationToken = default ) => WriteToServerAsync ( DataRowsValuesEnumerator . Create ( dataTable ) , IOBehavior . Synchronous , CancellationToken . None ) . AsTask ( ) ;
33
34
#else
34
- public ValueTask WriteToServerAsync ( DataTable dataTable , CancellationToken cancellationToken = default ) => WriteToServerAsync ( dataTable , IOBehavior . Asynchronous , cancellationToken ) ;
35
+ public ValueTask WriteToServerAsync ( DataTable dataTable , CancellationToken cancellationToken = default ) => WriteToServerAsync ( DataRowsValuesEnumerator . Create ( dataTable ) , IOBehavior . Synchronous , CancellationToken . None ) ;
35
36
#endif
36
37
38
+ public void WriteToServer ( IEnumerable < DataRow > dataRows , int columnCount ) => WriteToServerAsync ( new DataRowsValuesEnumerator ( dataRows , columnCount ) , IOBehavior . Synchronous , CancellationToken . None ) . GetAwaiter ( ) . GetResult ( ) ;
37
39
#if ! NETSTANDARD2_1 && ! NETCOREAPP3_0
38
- private async ValueTask < int > WriteToServerAsync ( DataTable dataTable , IOBehavior ioBehavior , CancellationToken cancellationToken )
40
+ public Task WriteToServerAsync ( IEnumerable < DataRow > dataRows , int columnCount , CancellationToken cancellationToken = default ) = > WriteToServerAsync ( new DataRowsValuesEnumerator ( dataRows , columnCount ) , IOBehavior . Asynchronous , cancellationToken ) . AsTask ( ) ;
39
41
#else
40
- private async ValueTask WriteToServerAsync ( DataTable dataTable , IOBehavior ioBehavior , CancellationToken cancellationToken )
42
+ public ValueTask WriteToServerAsync ( IEnumerable < DataRow > dataRows , int columnCount , CancellationToken cancellationToken = default ) => WriteToServerAsync ( new DataRowsValuesEnumerator ( dataRows , columnCount ) , IOBehavior . Asynchronous , cancellationToken ) ;
41
43
#endif
42
- {
43
- using var reader = dataTable . CreateDataReader ( ) ;
44
- await WriteToServerAsync ( reader , ioBehavior , cancellationToken ) ;
45
- #if ! NETSTANDARD2_1 && ! NETCOREAPP3_0
46
- return 0 ;
47
- #endif
48
- }
49
44
#endif
50
45
51
- public void WriteToServer ( IDataReader dataReader ) => WriteToServerAsync ( dataReader , IOBehavior . Synchronous , CancellationToken . None ) . GetAwaiter ( ) . GetResult ( ) ;
46
+ public void WriteToServer ( IDataReader dataReader ) => WriteToServerAsync ( DataReaderValuesEnumerator . Create ( dataReader ) , IOBehavior . Synchronous , CancellationToken . None ) . GetAwaiter ( ) . GetResult ( ) ;
52
47
#if ! NETSTANDARD2_1 && ! NETCOREAPP3_0
53
- public Task WriteToServerAsync ( IDataReader dataReader , CancellationToken cancellationToken = default ) => WriteToServerAsync ( dataReader , IOBehavior . Asynchronous , cancellationToken ) . AsTask ( ) ;
48
+ public Task WriteToServerAsync ( IDataReader dataReader , CancellationToken cancellationToken = default ) => WriteToServerAsync ( DataReaderValuesEnumerator . Create ( dataReader ) , IOBehavior . Asynchronous , cancellationToken ) . AsTask ( ) ;
54
49
#else
55
- public ValueTask WriteToServerAsync ( IDataReader dataReader , CancellationToken cancellationToken = default ) => WriteToServerAsync ( dataReader , IOBehavior . Asynchronous , cancellationToken ) ;
50
+ public ValueTask WriteToServerAsync ( IDataReader dataReader , CancellationToken cancellationToken = default ) => WriteToServerAsync ( DataReaderValuesEnumerator . Create ( dataReader ) , IOBehavior . Asynchronous , cancellationToken ) ;
56
51
#endif
57
52
58
53
#if ! NETSTANDARD2_1 && ! NETCOREAPP3_0
59
- private async ValueTask < int > WriteToServerAsync ( IDataReader dataReader , IOBehavior ioBehavior , CancellationToken cancellationToken )
54
+ private async ValueTask < int > WriteToServerAsync ( IValuesEnumerator values , IOBehavior ioBehavior , CancellationToken cancellationToken )
60
55
#else
61
- private async ValueTask WriteToServerAsync ( IDataReader dataReader , IOBehavior ioBehavior , CancellationToken cancellationToken )
56
+ private async ValueTask WriteToServerAsync ( IValuesEnumerator values , IOBehavior ioBehavior , CancellationToken cancellationToken )
62
57
#endif
63
58
{
64
59
var tableName = DestinationTableName ?? throw new InvalidOperationException ( "DestinationTableName must be set before calling WriteToServer" ) ;
@@ -73,7 +68,7 @@ private async ValueTask WriteToServerAsync(IDataReader dataReader, IOBehavior io
73
68
LineTerminator = "\n " ,
74
69
Local = true ,
75
70
NumberOfLinesToSkip = 0 ,
76
- Source = dataReader ?? throw new ArgumentNullException ( nameof ( dataReader ) ) ,
71
+ Source = values ?? throw new ArgumentNullException ( nameof ( values ) ) ,
77
72
TableName = tableName ,
78
73
Timeout = BulkCopyTimeout ,
79
74
} ;
@@ -129,26 +124,25 @@ private async ValueTask WriteToServerAsync(IDataReader dataReader, IOBehavior io
129
124
static string QuoteIdentifier ( string identifier ) => "`" + identifier . Replace ( "`" , "``" ) + "`" ;
130
125
}
131
126
132
- internal static async Task SendDataReaderAsync ( MySqlConnection connection , IDataReader dataReader , IOBehavior ioBehavior , CancellationToken cancellationToken )
127
+ internal static async Task SendDataReaderAsync ( MySqlConnection connection , IValuesEnumerator valuesEnumerator , IOBehavior ioBehavior , CancellationToken cancellationToken )
133
128
{
134
129
// rent a buffer that can fit in one packet
135
130
const int maxLength = 16_777_200 ;
136
131
var buffer = ArrayPool < byte > . Shared . Rent ( maxLength + 1 ) ;
137
132
var outputIndex = 0 ;
138
- var dbDataReader = dataReader as DbDataReader ;
139
133
140
134
try
141
135
{
142
- var values = new object ? [ dataReader . FieldCount ] ;
136
+ var values = new object ? [ valuesEnumerator . FieldCount ] ;
143
137
while ( true )
144
138
{
145
- var hasMore = ioBehavior == IOBehavior . Asynchronous && dbDataReader is object ?
146
- await dbDataReader . ReadAsync ( cancellationToken ) . ConfigureAwait ( false ) :
147
- dataReader . Read ( ) ;
139
+ var hasMore = ioBehavior == IOBehavior . Asynchronous ?
140
+ await valuesEnumerator . MoveNextAsync ( ) . ConfigureAwait ( false ) :
141
+ valuesEnumerator . MoveNext ( ) ;
148
142
if ( ! hasMore )
149
143
break ;
150
144
151
- dataReader . GetValues ( values ) ;
145
+ valuesEnumerator . GetValues ( values ) ;
152
146
retryRow :
153
147
var startOutputIndex = outputIndex ;
154
148
var wroteRow = true ;
0 commit comments