Here is example of Generic of Bulk Insert
public async Task CreateBulkAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default)
{
var options = SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.CheckConstraints |
SqlBulkCopyOptions.KeepNulls;
var props = _context.Model.FindEntityType(typeof(T)).GetProperties();
// Берем connection и !не закрываем! это connection контекста, поэтому он сам этим управляет
if (_context.Database.GetDbConnection() is SqlConnection connection)
{
if (connection.State == ConnectionState.Closed)
{
await connection.OpenAsync(cancellationToken);
}
using var sqlBulkCopy = new SqlBulkCopy(connection, options, null);
{
sqlBulkCopy.DestinationTableName = $"dbo.{typeof(T).Name}";
foreach (var property in props)
{
sqlBulkCopy.ColumnMappings.Add(property.Name, property.Name);
}
var dt = entities.EntityToDataTable();
await sqlBulkCopy.WriteToServerAsync(dt, cancellationToken);
}
}
else
{
throw new ArgumentNullException(nameof(connection));
}
}
Here EntityToDataTable function code:
public static DataTable EntityToDataTable<T>(this IEnumerable<T> source)
{
var dataTable = new DataTable(typeof(T).Name);
var props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in props)
{
dataTable.Columns.Add(prop.Name, prop.PropertyType.Name.Contains("Nullable") ? typeof(string) : prop.PropertyType);
}
foreach (T item in source)
{
var values = new object[props.Length];
for (var i = 0; i < props.Length; i++)
{
values[i] = props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
return dataTable;
}