using Dapper; using Newtonsoft.Json.Linq; using System.Data; using System.Data.Common; using System.Net.WebSockets; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Xml.Linq; namespace TWASys_App.Dapper.AExtentions { public static class DapperCommand { public static dynamic QueryInsert(T obj) { return QueryInsert(obj, new Dictionary()); } public static dynamic QueryInsert(T obj, Dictionary data, int IdTable = 100) { var type = typeof(T); var tableName = TableMapper.GetTableName(type); var allProperties = PropertiesCache.TypePropertiesCache(type); var keyProperties = PropertiesCache.KeyPropertiesCache(type); var fkProperties = PropertiesCache.FKPropertiesCache(type); var computedProperties = PropertiesCache.ComputedPropertiesCache(type); var columns = PropertiesCache.GetColumnNamesCache(type); var insertProperties = allProperties.Except(computedProperties).Except(fkProperties).ToList(); var insertPropertiesString = string.Empty; var stringKeyProperty = string.Empty; var keyAI = string.Empty; var flag = false; var q = string.Empty; if (keyProperties.Count > 0) { flag = true; insertProperties = insertProperties.Except(keyProperties).ToList(); stringKeyProperty = GetColumnsString(keyProperties.ToList(), columns); keyAI = $@"SET @{GetColumnsString(keyProperties.ToList(), columns, IdTable.ToString(), "")} := LAST_INSERT_ID();"; } insertPropertiesString = GetColumnsString(insertProperties, columns); var fkPropertiesString = string.Empty; var fkValuesString = string.Empty; if (data.Count > 0) { fkPropertiesString = GetColumnsString(fkProperties, columns); fkValuesString = string.Join(", ", fkProperties.Select(u => { var ok = data.TryGetValue(u.Name, out var v); if (ok) { return $"@tb{v?.Name}_{u.Name}"; } else { return $"@tb{IdTable}_{u.Name}"; } })); fkPropertiesString += (string.IsNullOrEmpty(fkPropertiesString))?"": ", "; fkValuesString += (string.IsNullOrEmpty(fkValuesString)) ? "" : ", "; } q = $@"INSERT INTO {FormatTableName(tableName)} ({fkPropertiesString + insertPropertiesString}) VALUES ({fkValuesString + GetColumnsString(insertProperties, columns, IdTable.ToString(), "@")}); {keyAI}"; return new { IsKeyAI = flag, Query = q, Name = IdTable.ToString(), KeyVar = stringKeyProperty }; } public static async Task Insert(this DbConnection connection, T obj, IDbTransaction? tx = null) { var type = typeof(T); var tableName = TableMapper.GetTableName(type); var allProperties = PropertiesCache.TypePropertiesCache(type); var keyProperties = PropertiesCache.KeyPropertiesCache(type); var computedProperties = PropertiesCache.ComputedPropertiesCache(type); var columns = PropertiesCache.GetColumnNamesCache(type); var insertProperties = allProperties.Except(computedProperties).ToList(); var insertPropertiesString = string.Empty; if (keyProperties.Count > 0) { insertProperties = insertProperties.Except(keyProperties).ToList(); insertPropertiesString = GetColumnsString(insertProperties, columns); var insertedId = await connection.QueryFirstAsync($@" INSERT INTO {FormatTableName(tableName)} ({insertPropertiesString}) VALUES ({GetColumnsString(insertProperties, columns, "@")}); SELECT LAST_INSERT_ID()", obj, tx); keyProperties[0].SetValue(obj, insertedId); } else { insertPropertiesString = GetColumnsString(insertProperties, columns); await connection.QueryFirstAsync($@" INSERT INTO {FormatTableName(tableName)}({insertPropertiesString}) VALUES ({GetColumnsString(insertProperties, columns, "@")})", obj, tx); } } public static async Task Update(this DbConnection connection, T obj) { var type = typeof(T); var tableName = TableMapper.GetTableName(type); var allProperties = PropertiesCache.TypePropertiesCache(type); var keyProperties = PropertiesCache.KeyPropertiesCache(type); var computedProperties = PropertiesCache.ComputedPropertiesCache(type); var columns = PropertiesCache.GetColumnNamesCache(type); T obj1 = Activator.CreateInstance(); var uProperties = allProperties.Except(computedProperties).Except(keyProperties).ToList(); var diffProperties = ComparePropertiesValue(obj, obj1, uProperties); await connection.QueryAsync($@" UPDATE {FormatTableName(tableName)} Set {GetUpdateString(diffProperties, columns, " , ")} WHERE {GetUpdateString(keyProperties, columns, " and ")}", obj); } private static List ComparePropertiesValue(T obj1, T obj2, IEnumerable properties) { List propertiesDiff = new List(); foreach (PropertyInfo property in properties) { if (property.GetValue(obj1, null) != property.GetValue(obj2, null)) { propertiesDiff.Add(property); } } return propertiesDiff; } private static string GetUpdateString(IEnumerable properties, IReadOnlyDictionary columnNames, string prefix) { return string.Join(prefix, properties.Select(p => $"{columnNames[p.Name]} = @{p.Name}")); } private static string GetColumnsString(IEnumerable properties, IReadOnlyDictionary columnNames, string tbName, string tablePrefix = "") { if (tbName != string.Empty) tbName = "tb" + tbName + "_"; if (tablePrefix == "target.") { return string.Join(", ", properties.Select(property => $"{tablePrefix}{columnNames[property.Name]} as {property.Name}")); } else if(tablePrefix == "@") { return string.Join(", ", properties.Select(property => $"{tablePrefix}{tbName + property.Name}")); } return string.Join(", ", properties.Select(property => $"{tablePrefix}{tbName + columnNames[property.Name].Replace("__", "")}")); } private static string GetColumnsString(IEnumerable properties, IReadOnlyDictionary columnNames, string tablePrefix = null) { return GetColumnsString(properties, columnNames, "", tablePrefix); } private static string FormatTableName(string table) { if (string.IsNullOrEmpty(table)) { return table; } var parts = table.Split('.'); if (parts.Length == 1) { return $"{table}"; } var tableName = ""; for (int i = 0; i < parts.Length; i++) { tableName += $"{parts[i]}"; if (i + 1 < parts.Length) { tableName += "."; } } return tableName; } } }