Skip to content

Commit 5eff408

Browse files
committed
Add async methods and improve DataBulkCopy mapping
1 parent 346eed9 commit 5eff408

File tree

4 files changed

+237
-55
lines changed

4 files changed

+237
-55
lines changed

src/FluentCommand.SqlServer/Bulk/DataBulkCopy.cs

Lines changed: 128 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Data;
2+
using System.Linq.Expressions;
23

34
using FluentCommand.Extensions;
45

@@ -194,22 +195,31 @@ public IDataBulkCopy Ignore(int sourceColumnOrdinal)
194195
return this;
195196
}
196197

197-
/// <summary>
198-
/// Copies all items in the supplied <see cref="IEnumerable{TEntity}"/> to the destination table using bulk copy.
199-
/// </summary>
200-
/// <typeparam name="TEntity">The type of the data elements.</typeparam>
201-
/// <param name="data">An enumerable collection of entities to be copied to the destination table.</param>
198+
/// <inheritdoc/>
199+
public IDataBulkCopy Ignore<TEntity, TValue>(Expression<Func<TEntity, TValue>> sourceProperty)
200+
where TEntity : class
201+
{
202+
return Mapping<TEntity>(b => b.Ignore(sourceProperty));
203+
}
204+
205+
/// <inheritdoc/>
202206
public void WriteToServer<TEntity>(IEnumerable<TEntity> data)
203207
where TEntity : class
204208
{
205209
using var dataReader = new ListDataReader<TEntity>(data);
206210
WriteToServer(dataReader);
207211
}
208212

209-
/// <summary>
210-
/// Copies all rows from the supplied <see cref="DataRow"/> array to the destination table using bulk copy.
211-
/// </summary>
212-
/// <param name="rows">An array of <see cref="DataRow"/> objects to be copied to the destination table.</param>
213+
/// <inheritdoc/>
214+
public async Task WriteToServerAsync<TEntity>(IEnumerable<TEntity> data, CancellationToken cancellationToken = default)
215+
where TEntity : class
216+
{
217+
using var dataReader = new ListDataReader<TEntity>(data);
218+
await WriteToServerAsync(dataReader, cancellationToken);
219+
}
220+
221+
222+
/// <inheritdoc/>
213223
public void WriteToServer(DataRow[] rows)
214224
{
215225
AssertDisposed();
@@ -230,32 +240,43 @@ public void WriteToServer(DataRow[] rows)
230240
}
231241
}
232242

233-
/// <summary>
234-
/// Copies all rows in the supplied <see cref="DataTable"/> to the destination table using bulk copy.
235-
/// </summary>
236-
/// <param name="table">A <see cref="DataTable"/> whose rows will be copied to the destination table.</param>
243+
/// <inheritdoc/>
244+
public async Task WriteToServerAsync(DataRow[] rows, CancellationToken cancellationToken = default)
245+
{
246+
AssertDisposed();
247+
248+
try
249+
{
250+
await _dataSession.EnsureConnectionAsync(cancellationToken);
251+
252+
using var bulkCopy = Create();
253+
254+
await bulkCopy.WriteToServerAsync(rows, cancellationToken);
255+
256+
bulkCopy.Close();
257+
}
258+
finally
259+
{
260+
_dataSession.ReleaseConnection();
261+
Dispose();
262+
}
263+
}
264+
265+
266+
/// <inheritdoc/>
237267
public void WriteToServer(DataTable table)
238268
{
239269
WriteToServer(table, 0);
240270
}
241271

242-
/// <summary>
243-
/// Copies only rows that match the supplied row state in the supplied <see cref="DataTable"/> to the destination table using bulk copy.
244-
/// </summary>
245-
/// <param name="table">A <see cref="DataTable"/> whose rows will be copied to the destination table.</param>
246-
/// <param name="rowState">A value from the <see cref="DataRowState"/> enumeration. Only rows matching the row state are copied to the destination.</param>
272+
/// <inheritdoc/>
247273
public void WriteToServer(DataTable table, DataRowState rowState)
248274
{
249275
AssertDisposed();
250276

251277
try
252278
{
253-
// resolve auto map
254-
if (_autoMap == true)
255-
{
256-
foreach (DataColumn column in table.Columns)
257-
Mapping(column.ColumnName, column.ColumnName);
258-
}
279+
ApplyAutoMapping(table);
259280

260281
_dataSession.EnsureConnection();
261282

@@ -271,25 +292,39 @@ public void WriteToServer(DataTable table, DataRowState rowState)
271292
}
272293
}
273294

274-
/// <summary>
275-
/// Copies all rows in the supplied <see cref="IDataReader"/> to the destination table using bulk copy.
276-
/// </summary>
277-
/// <param name="reader">An <see cref="IDataReader"/> whose rows will be copied to the destination table.</param>
295+
/// <inheritdoc/>
296+
public async Task WriteToServerAsync(DataTable table, DataRowState rowState = 0, CancellationToken cancellationToken = default)
297+
{
298+
AssertDisposed();
299+
300+
try
301+
{
302+
ApplyAutoMapping(table);
303+
304+
await _dataSession.EnsureConnectionAsync(cancellationToken);
305+
306+
using var bulkCopy = Create();
307+
308+
await bulkCopy.WriteToServerAsync(table, rowState, cancellationToken);
309+
310+
bulkCopy.Close();
311+
}
312+
finally
313+
{
314+
_dataSession.ReleaseConnection();
315+
Dispose();
316+
}
317+
}
318+
319+
320+
/// <inheritdoc/>
278321
public void WriteToServer(IDataReader reader)
279322
{
280323
AssertDisposed();
281324

282325
try
283326
{
284-
// resolve auto map
285-
if (_autoMap == true)
286-
{
287-
for (int i = 0; i < reader.FieldCount; i++)
288-
{
289-
var name = reader.GetName(i);
290-
Mapping(name, name);
291-
}
292-
}
327+
ApplyAutoMapping(reader);
293328

294329
_dataSession.EnsureConnection();
295330

@@ -305,10 +340,65 @@ public void WriteToServer(IDataReader reader)
305340
}
306341
}
307342

343+
/// <inheritdoc/>
344+
public async Task WriteToServerAsync(IDataReader reader, CancellationToken cancellationToken = default)
345+
{
346+
AssertDisposed();
347+
348+
try
349+
{
350+
ApplyAutoMapping(reader);
351+
352+
await _dataSession.EnsureConnectionAsync(cancellationToken);
353+
354+
using var bulkCopy = Create();
355+
356+
await bulkCopy.WriteToServerAsync(reader, cancellationToken);
357+
358+
bulkCopy.Close();
359+
}
360+
finally
361+
{
362+
_dataSession.ReleaseConnection();
363+
Dispose();
364+
}
365+
}
366+
367+
368+
/// <summary>
369+
/// Applies automatic column mappings based on the <see cref="IDataReader"/> field names.
370+
/// </summary>
371+
/// <param name="reader">The data reader containing the field schema.</param>
372+
private void ApplyAutoMapping(IDataReader reader)
373+
{
374+
if (_autoMap != true)
375+
return;
376+
377+
for (int i = 0; i < reader.FieldCount; i++)
378+
{
379+
var name = reader.GetName(i);
380+
Mapping(name, name);
381+
}
382+
}
383+
384+
/// <summary>
385+
/// Applies automatic column mappings based on the <see cref="DataTable"/> column names.
386+
/// </summary>
387+
/// <param name="table">The data table containing the column schema.</param>
388+
private void ApplyAutoMapping(DataTable table)
389+
{
390+
if (_autoMap != true)
391+
return;
392+
393+
foreach (DataColumn column in table.Columns)
394+
Mapping(column.ColumnName, column.ColumnName);
395+
}
396+
397+
308398
/// <summary>
309399
/// Creates and configures a <see cref="SqlBulkCopy"/> instance based on the current settings and mappings.
310400
/// </summary>
311-
/// <returns>A configured <see cref="SqlBulkCopy"/> instance.</returns>
401+
/// <returns>A configured <see cref="SqlBulkCopy"/> instance ready for bulk copy operations.</returns>
312402
/// <exception cref="InvalidOperationException">
313403
/// Thrown if the underlying connection is not a <see cref="SqlConnection"/>.
314404
/// </exception>

src/FluentCommand.SqlServer/Bulk/DataBulkCopyExtensions.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
using FluentCommand.Extensions;
2+
using FluentCommand.Reflection;
3+
14
using Microsoft.Data.SqlClient;
25

36
namespace FluentCommand.Bulk;
@@ -20,4 +23,25 @@ public static IDataBulkCopy BulkCopy(this IDataSession session, string destinati
2023
var bulkCopy = new DataBulkCopy(session, destinationTable);
2124
return bulkCopy;
2225
}
26+
27+
/// <summary>
28+
/// Starts a bulk copy operation using the specified data session and destination table name.
29+
/// </summary>
30+
/// <typeparam name="TEntity">The type of the entity to be copied.</typeparam>
31+
/// <param name="session">The <see cref="IDataSession"/> to use for the bulk copy operation.</param>
32+
/// <returns>
33+
/// An <see cref="IDataBulkCopy"/> instance for configuring and executing the bulk copy operation.
34+
/// </returns>
35+
public static IDataBulkCopy BulkCopy<TEntity>(this IDataSession session)
36+
{
37+
var typeAccessor = TypeAccessor.GetAccessor<TEntity>();
38+
var destinationTable = typeAccessor.TableSchema.HasValue()
39+
? $"{typeAccessor.TableSchema}.{typeAccessor.TableName}"
40+
: typeAccessor.TableName;
41+
42+
var bulkCopy = new DataBulkCopy(session, destinationTable);
43+
bulkCopy.AutoMap();
44+
45+
return bulkCopy;
46+
}
2347
}

0 commit comments

Comments
 (0)