Files
zszq-trs/YLErpDAL/DataBase/EFExtensions/MySqlBulkExtensions.cs
T
2024-06-11 18:36:13 +08:00

133 lines
5.2 KiB
C#

using BaseOUDAL.EFExtensions;
using Dapper;
using MySqlConnector;
using System.Data;
using System.Reflection;
using System.Text;
namespace YLErp.BLL
{
public static class MySqlBulkExtensions
{
public static void BulkInsert<T>(this DbContext context, IEnumerable<T> entities)
{
if (entities != null && entities.Any())
{
var conn = context.Database.GetDbConnection() as MySqlConnection;
BulkInsert(conn, entities);
}
}
/// <summary>
/// Inserts entities into table <typeparamref name="T"/>s (by default).
/// </summary>
/// <typeparam name="T">The type being inserted.</typeparam>
/// <param name="connection">Open SqlConnection</param>
/// <param name="data">Entities to insert</param>
/// <param name="transaction">The transaction to run under, null (the default) if none</param>
/// <param name="batchSize">Number of bulk items inserted together, 0 (the default) if all</param>
/// <param name="bulkCopyTimeout">Number of seconds before bulk command execution timeout, 30 (the default)</param>
private static void BulkInsert<T>(MySqlConnection connection, IEnumerable<T> data, IDbTransaction transaction = null)
{
BulkInsert(connection, typeof(T), data.Cast<object>(), transaction);
}
/// <summary>
/// Inserts entities into table.
/// by default, the table is named after the data type specified.
/// </summary>
/// <param name="connection">Open SqlConnection</param>
/// <param name="type">The type being inserted.</param>
/// <param name="data">Entities to insert</param>
/// <param name="transaction">The transaction to run under, null (the default) if none</param>
/// <param name="batchSize">Number of bulk items inserted together, 0 (the default) if all</param>
/// <param name="bulkCopyTimeout">Number of seconds before bulk command execution timeout, 30 (the default)</param>
private static void BulkInsert(MySqlConnection connection, Type type, IEnumerable<object> data, IDbTransaction transaction = null)
{
var tableName = TableMapper.GetTableName(type);
var allProperties = PropertiesCache.TypePropertiesCache(type);
var computedProperties = PropertiesCache.ComputedPropertiesCache(type);
var columns = PropertiesCache.GetColumnNamesCache(type);
var selProperties = allProperties.Except(computedProperties).ToList();
if (!selProperties.Any())
{
return;
}
var selcols = string.Join(", ", selProperties.Select(property => $"`{columns[property.Name]}`"));
var sCommand = new StringBuilder();
sCommand.Append("INSERT INTO `").Append(tableName)
.Append("` (").Append(selcols).Append(") VALUES ");
DumpInertValues(sCommand, data, selProperties).AppendLine(";");
var sql = sCommand.ToString();
System.Diagnostics.Debug.WriteLine("$$$$$$$$$$");
System.Diagnostics.Debug.WriteLine(sql);
connection.Execute(sql, null, transaction);
}
private static StringBuilder DumpInertValues<T>(StringBuilder sb, IEnumerable<T> data, IList<PropertyInfo> properties)
{
System.Diagnostics.Debug.Assert(properties.Count > 0);
var typeCasts = new Type[properties.Count];
for (var i = 0; i < properties.Count; i++)
{
if (properties[i].PropertyType.IsEnum)
{
typeCasts[i] = Enum.GetUnderlyingType(properties[i].PropertyType);
}
else
{
typeCasts[i] = null;
}
}
foreach (var item in data)
{
sb.AppendLine().Append("(");
for (var i = 0; i < properties.Count; i++)
{
var value = properties[i].GetValue(item, null);
if (value == null)
{
sb.Append("NULL");
}
else if (value is string str)
{
sb.Append('\'').Append(MySqlHelper.EscapeString(str)).Append('\'');
}
else if (value is DateTime dt)
{
sb.Append('\'').Append(dt.ToString("yyyy-MM-dd HH:mm:ss")).Append('\'');
}
else if (value is double dd)
{
sb.Append(double.IsNaN(dd) ? 0 : dd);
}
else if (typeCasts[i] != null)
{
sb.Append(Convert.ChangeType(value, typeCasts[i]));
}
else
{
sb.Append(value);
}
sb.Append(',');
}
sb.Remove(sb.Length - 1, 1).Append("),");
}
return sb.Remove(sb.Length - 1, 1);
}
}
}