MES-ETL/ConsoleApp2/Services/MySqlDestination.cs

172 lines
5.1 KiB
C#
Raw Normal View History

2023-12-29 16:16:05 +08:00
using System.Text;
using ConsoleApp2.Helpers;
using Microsoft.Extensions.Logging;
using MySqlConnector;
2024-01-12 16:50:37 +08:00
using ServiceStack;
2023-12-29 16:16:05 +08:00
namespace ConsoleApp2.Services;
2024-01-04 09:00:44 +08:00
/// <summary>
/// Mysql导出
/// </summary>
2023-12-29 16:16:05 +08:00
public class MySqlDestination : IDisposable, IAsyncDisposable
{
private readonly Dictionary<string, IList<DataRecord>> _recordCache;
private readonly MySqlConnection _conn;
private readonly ILogger _logger;
private readonly bool _prettyOutput;
2024-01-12 16:50:37 +08:00
private readonly int _maxAllowPacket;
private readonly ProcessContext _context;
private static StringBuilder recordSb = new StringBuilder();
public MySqlDestination(string connStr, ILogger logger, ProcessContext context,bool prettyOutput = false)
2023-12-29 16:16:05 +08:00
{
_conn = new MySqlConnection(connStr);
_conn.Open();
_recordCache = new Dictionary<string, IList<DataRecord>>();
_logger = logger;
2024-01-12 16:50:37 +08:00
_context = context;
2023-12-29 16:16:05 +08:00
_prettyOutput = prettyOutput;
2024-01-12 16:50:37 +08:00
}
2023-12-29 16:16:05 +08:00
public Task WriteRecordAsync(DataRecord record)
{
_recordCache.AddOrUpdate(record.TableName, [record], (key, value) =>
{
value.Add(record);
return value;
});
return Task.CompletedTask;
}
public async Task WriteRecordsAsync(IEnumerable<DataRecord> records)
{
foreach (var record in records)
{
await WriteRecordAsync(record);
}
}
2024-01-12 16:50:37 +08:00
public async Task FlushAsync(int maxAllowPacket)
2023-12-29 16:16:05 +08:00
{
if (_recordCache.Count == 0)
return;
2024-01-12 16:50:37 +08:00
//var cmd = _conn.CreateCommand();
//cmd.CommandTimeout = 3 * 60;
2023-12-29 16:16:05 +08:00
try
{
2024-01-12 16:50:37 +08:00
var excuseList = GetExcuseList(_recordCache, maxAllowPacket, _prettyOutput);
//foreach (var insertSql in excuseList)
//{
// //cmd.CommandText = insertSql;
// //await cmd.ExecuteNonQueryAsync();
// //_logger.LogInformation(@"do insert completed!size:{Length}", cmd.CommandText.Length);
//}
2023-12-29 16:16:05 +08:00
_recordCache.Clear();
}
catch (Exception e)
{
2024-01-12 16:50:37 +08:00
//_logger.LogCritical(e, "Error when flushing records, sql: {Sql}", cmd.CommandText.Omit(1000));
_context.AddException(e);
2023-12-29 16:16:05 +08:00
throw;
}
2024-01-04 09:00:44 +08:00
finally
{
2024-01-12 16:50:37 +08:00
//await cmd.DisposeAsync();
2024-01-04 09:00:44 +08:00
}
2023-12-29 16:16:05 +08:00
}
2024-01-12 16:50:37 +08:00
public static IList<string> GetExcuseList(IDictionary<string, IList<DataRecord>> tableRecords,int maxAllowPacket,
bool prettyOutput = false)
2023-12-29 16:16:05 +08:00
{
2024-01-12 16:50:37 +08:00
var resultList = new List<string>();
var headerSb = string.Empty;
//var recordSb = new StringBuilder();
recordSb.Clear();
2023-12-29 16:16:05 +08:00
foreach (var (tableName, records) in tableRecords)
{
if (records.Count == 0)
continue;
2024-01-12 16:50:37 +08:00
headerSb=$"INSERT INTO `{tableName}`(";
2023-12-29 16:16:05 +08:00
for (var i = 0; i < records[0].Headers.Length; i++)
{
var header = records[0].Headers[i];
2024-01-12 16:50:37 +08:00
headerSb+=$"`{header}`";
2023-12-29 16:16:05 +08:00
if (i != records[0].Headers.Length - 1)
2024-01-12 16:50:37 +08:00
headerSb.Append(',');
2023-12-29 16:16:05 +08:00
}
2024-01-12 16:50:37 +08:00
headerSb+=") VALUES ";
2023-12-29 16:16:05 +08:00
if (prettyOutput)
2024-01-12 16:50:37 +08:00
headerSb+="/r/n";
2023-12-29 16:16:05 +08:00
2024-01-12 16:50:37 +08:00
var sbList = new List<string>();
var currentLength = headerSb.Length;
2023-12-29 16:16:05 +08:00
for (var i = 0; i < records.Count; i++)
{
var record = records[i];
2024-01-12 16:50:37 +08:00
recordSb.Append('(');
2023-12-29 16:16:05 +08:00
for (var j = 0; j < record.Fields.Length; j++)
{
var field = record.Fields[j];
2024-01-12 16:50:37 +08:00
recordSb.Append(field);
2023-12-29 16:16:05 +08:00
if (j != record.Fields.Length - 1)
2024-01-12 16:50:37 +08:00
recordSb.Append(',');
2023-12-29 16:16:05 +08:00
}
2024-01-12 16:50:37 +08:00
recordSb.Append(')');
2023-12-29 16:16:05 +08:00
2024-01-12 16:50:37 +08:00
//if (i != records.Count - 1) // not last field
// recordSb.Append(',');
if (prettyOutput) recordSb.AppendLine();
2023-12-29 16:16:05 +08:00
2024-01-12 16:50:37 +08:00
if (currentLength + recordSb.Length >= maxAllowPacket)
{
var insertSb = headerSb;
insertSb+=string.Join(",", sbList);
insertSb += ";";
resultList.Add(insertSb);
insertSb=String.Empty;
sbList.Clear();
currentLength = headerSb.Length;
sbList.Add(recordSb.ToString());
}
else
{
sbList.Add(recordSb.ToString());
}
currentLength += recordSb.Length;
recordSb.Clear();
}
if (sbList.Count > 0)
{
var insertSb = headerSb.ToString();
insertSb += string.Join(",", sbList);
insertSb += ";";
resultList.Add(insertSb.ToString());
insertSb=string.Empty;
}
headerSb=string.Empty;
2023-12-29 16:16:05 +08:00
}
2024-01-12 16:50:37 +08:00
return resultList;
2023-12-29 16:16:05 +08:00
}
public void Dispose()
{
2024-01-04 09:00:44 +08:00
_conn.Close();
2023-12-29 16:16:05 +08:00
_conn.Dispose();
}
public async ValueTask DisposeAsync()
{
2024-01-04 09:00:44 +08:00
await _conn.CloseAsync();
2023-12-29 16:16:05 +08:00
await _conn.DisposeAsync();
}
}