Optimize structure

This commit is contained in:
2024-02-10 17:12:26 +08:00
parent aa7041962a
commit 571805250b
26 changed files with 193 additions and 52 deletions

View File

@@ -1,64 +0,0 @@
using System.Data;
using MySqlConnector;
namespace MesETL.App.Helpers;
public static class DatabaseHelper
{
public static MySqlConnection CreateConnection(string connStr)
{
var newConnStr = new MySqlConnectionStringBuilder(connStr)
{
ConnectionTimeout = 30,
DefaultCommandTimeout = 0,
}.ConnectionString;
return new MySqlConnection(newConnStr);
}
public static async Task<DataSet> QueryTableAsync(string connStr, string sql)
{
await using var conn = CreateConnection(connStr);
if(conn.State is not ConnectionState.Open)
await conn.OpenAsync();
await using var cmd = conn.CreateCommand();
cmd.CommandText = sql;
var ds = new DataSet();
new MySqlDataAdapter(cmd).Fill(ds);
return ds;
}
public static async Task<object?> QueryScalarAsync(string connStr, string sql)
{
await using var conn = CreateConnection(connStr);
if(conn.State is not ConnectionState.Open)
await conn.OpenAsync();
await using var cmd = conn.CreateCommand();
cmd.CommandText = sql;
return await cmd.ExecuteScalarAsync();
}
public static async Task<int> NonQueryAsync(string connStr, string sql)
{
await using var conn = CreateConnection(connStr);
if(conn.State is not ConnectionState.Open)
await conn.OpenAsync();
await using var cmd = conn.CreateCommand();
cmd.CommandText = sql;
return await cmd.ExecuteNonQueryAsync();
}
public static async Task<int> TransactionAsync(string connStr, string sql, params MySqlParameter[] parameters)
{
await using var conn = CreateConnection(connStr);
if(conn.State is not ConnectionState.Open)
await conn.OpenAsync();
await using var trans = await conn.BeginTransactionAsync();
await using var cmd = conn.CreateCommand();
cmd.CommandText = sql;
cmd.Transaction = trans;
cmd.Parameters.AddRange(parameters);
var rows = await cmd.ExecuteNonQueryAsync();
await trans.CommitAsync();
return rows;
}
}

View File

@@ -1,30 +0,0 @@
namespace MesETL.App.Helpers;
public static class DictionaryExtensions
{
/// <summary>
/// 根据指定的键是否存在来添加或是更新字典
/// </summary>
/// <param name="this"></param>
/// <param name="key">指定的键</param>
/// <param name="addValue">如果指定的键不存在,则向字典添加该值</param>
/// <param name="updateFactory">如果指定的键存在,则根据该委托的返回值修改字典中对应的值</param>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
/// <returns>添加或是修改后的值</returns>
public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, TValue addValue,
Func<TKey, TValue, TValue> updateFactory)
{
if (!@this.TryGetValue(key, out var value))
{
@this.Add(key, addValue);
}
else
{
@this[key] = updateFactory(key, value);
}
return @this[key];
}
}

View File

@@ -1,71 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
namespace MesETL.App.Helpers;
#nullable disable
public static class EnumerableExtensions
{
public static string ToMarkdownTable<
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties |
DynamicallyAccessedMemberTypes.NonPublicProperties |
DynamicallyAccessedMemberTypes.PublicFields |
DynamicallyAccessedMemberTypes.NonPublicFields)] T>(this IEnumerable<T> source)
{
var properties = typeof(T).GetRuntimeProperties();
var fields = typeof(T)
.GetRuntimeFields()
.Where(f => f.IsPublic);
var gettables = Enumerable.Union(
properties.Select(p => new { p.Name, GetValue = (Func<object, object>)p.GetValue, Type = p.PropertyType }),
fields.Select(p => new { p.Name, GetValue = (Func<object, object>)p.GetValue, Type = p.FieldType }));
var maxColumnValues = source
.Select(x => gettables.Select(p => p.GetValue(x)?.ToString()?.Length ?? 0))
.Union(new[] { gettables.Select(p => p.Name.Length) }) // Include header in column sizes
.Aggregate(
new int[gettables.Count()].AsEnumerable(),
(accumulate, x) => accumulate.Zip(x, Math.Max))
.ToArray();
var columnNames = gettables.Select(p => p.Name);
var headerLine = "| " + string.Join(" | ", columnNames.Select((n, i) => n.PadRight(maxColumnValues[i]))) + " |";
var isNumeric = new Func<Type, bool>(type =>
type == typeof(Byte) ||
type == typeof(SByte) ||
type == typeof(UInt16) ||
type == typeof(UInt32) ||
type == typeof(UInt64) ||
type == typeof(Int16) ||
type == typeof(Int32) ||
type == typeof(Int64) ||
type == typeof(Decimal) ||
type == typeof(Double) ||
type == typeof(Single));
var rightAlign = new Func<Type, char>(type => isNumeric(type) ? ':' : ' ');
var headerDataDividerLine =
"| " +
string.Join(
"| ",
gettables.Select((g, i) => new string('-', maxColumnValues[i]) + rightAlign(g.Type))) +
"|";
var lines = new[]
{
headerLine,
headerDataDividerLine,
}.Union(
source
.Select(s =>
"| " + string.Join(" | ",
gettables.Select((n, i) => (n.GetValue(s)?.ToString() ?? "").PadRight(maxColumnValues[i]))) +
" |"));
return lines
.Aggregate((p, c) => p + Environment.NewLine + c);
}
}

View File

@@ -1,70 +0,0 @@
using System.Globalization;
using System.Text;
namespace MesETL.App.Helpers;
public static class StringExtensions
{
/// <summary>
/// 截断字符串
/// </summary>
/// <param name="this"></param>
/// <param name="maxLength">截断长度</param>
/// <returns></returns>
public static string Omit(this ReadOnlySpan<char> @this, int maxLength)
{
if (@this.Length > maxLength)
return @this[..maxLength].ToString() + "...";
return @this.ToString();
}
/// <summary>
/// 截断字符串
/// </summary>
/// <param name="this"></param>
/// <param name="maxLength">截断长度</param>
/// <returns></returns>
public static string Omit(this string @this, int maxLength) => Omit(@this.AsSpan(), maxLength);
/// <summary>
/// 将16进制字符串转换为字符串
/// </summary>
/// <param name="hexString"></param>
/// <param name="encoding"></param>
/// <returns></returns>
public static string FromHex(ReadOnlySpan<char> hexString, Encoding? encoding = null)
{
encoding ??= Encoding.UTF8;
var realLength = 0;
for (var i = hexString.Length - 2; i >= 0; i -= 2)
{
var b = byte.Parse(hexString.Slice(i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
if (b != 0) //not NULL character
{
realLength = i + 2;
break;
}
}
var bytes = new byte[realLength / 2];
for (var i = 0; i < bytes.Length; i++)
{
bytes[i] = byte.Parse(hexString.Slice(i * 2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
return encoding.GetString(bytes);
}
/// <summary>
/// 检查是否为JSON字符串
/// </summary>
/// <param name="hexStr"></param>
/// <returns></returns>
public static bool CheckJsonHex(ReadOnlySpan<char> hexStr)
{
if (hexStr.Length < 2)
return false;
return FromHex(hexStr[..2]) is ['{'] or ['['];
}
}

View File

@@ -1,19 +0,0 @@
namespace MesETL.App.Helpers;
public static class TaskExtensions
{
public static async Task WaitUntil(Func<bool> condition, int pollDelay = 25, CancellationToken ct = default)
{
try
{
while (!condition())
{
await Task.Delay(pollDelay, ct);
}
}
catch(TaskCanceledException)
{
// CancellationToken激活时Task.Delay通过抛异常来结束停止等待不用管它
}
}
}