Optimize structure
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
@@ -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];
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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 ['['];
|
||||
}
|
||||
}
|
@@ -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通过抛异常来结束停止等待,不用管它
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user