using System.Reflection; using MySql.Data.MySqlClient; using OMS.NET.Common; namespace OMS.NET.DbClass { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public class TableAttribute : Attribute { public string TableName { get; } public TableAttribute(string tableName) { TableName = tableName; } } [AttributeUsage(AttributeTargets.Property, Inherited = false)] public class ColumnAttribute : Attribute { public string ColumnName { get; } public bool IsPrimaryKey { get; } public bool IsIdentity { get; } // 是否自增列 public ColumnAttribute(string columnName, bool isPrimaryKey = false, bool isIdentity = false) { ColumnName = columnName; IsPrimaryKey = isPrimaryKey; IsIdentity = isIdentity; } } public class BaseObject { private static string GetTableName(Type type) { var attr = type.GetCustomAttribute(); return attr?.TableName ?? throw new Exception($"{type.Name} 没有指定数据表"); } private static IEnumerable GetProperties(Type type) { return type.GetProperties() .Where(p => p.GetCustomAttribute() != null); } private static PropertyInfo GetPrimaryKeyProperties(Type type) { var primaryKeyProperties = GetProperties(type) .Where(p => p.GetCustomAttribute()?.IsPrimaryKey == true) .ToList(); if (primaryKeyProperties.Count == 0) { throw new InvalidOperationException("No primary key defined for the class."); } if (primaryKeyProperties.Count != 1) { throw new InvalidOperationException("Multiple primary keys defined for the class. Only one primary key is allowed."); } return primaryKeyProperties.First(); } private static IEnumerable GetNonKeyProperties(Type type) { return GetProperties(type) .Where(p => p.GetCustomAttribute()?.IsPrimaryKey == false); } private static PropertyInfo? GetIdentityKeyProperty(Type type) { var primaryKey = GetPrimaryKeyProperties(type); return (primaryKey.GetCustomAttribute()!.IsIdentity == true) ? null : primaryKey; } private static string GetInsertSql(Type type) { var tableName = GetTableName(type); var identityKey = GetIdentityKeyProperty(type); var columns = GetNonKeyProperties(type) .Select(p => p.GetCustomAttribute()!.ColumnName).ToList(); var values = GetNonKeyProperties(type) .Select(p => "@" + p.Name).ToList(); if (identityKey != null) { // Exclude the identity key from columns and values for insert statement columns.Add(identityKey.GetCustomAttribute()!.ColumnName); values.Add("@" + identityKey.Name); } return $"INSERT INTO {tableName} ({string.Join(", ", columns)}) VALUES ({string.Join(", ", values)})"; } private static string GetUpdateSql(Type type) { var tableName = GetTableName(type); var setClause = string.Join(", ", GetNonKeyProperties(type) .Select(p => $"{p.GetCustomAttribute()!.ColumnName} = @{p.Name}")); var primaryKey = GetPrimaryKeyProperties(type); var whereClause = $"{primaryKey.GetCustomAttribute()!.ColumnName} = @{primaryKey.Name}"; return $"UPDATE {tableName} SET {setClause} WHERE {whereClause}"; } private static string GetDeleteSql(Type type) { var tableName = GetTableName(type); var primaryKey = GetPrimaryKeyProperties(type); var whereClause = $"{primaryKey.GetCustomAttribute()!.ColumnName} = @{primaryKey.Name}"; return $"DELETE FROM {tableName} WHERE {whereClause}"; } private static string GetSelectSql(Type type) { var tableName = GetTableName(type); var columns = string.Join(", ", GetProperties(type) .Select(p => p.GetCustomAttribute()!.ColumnName)); return $"SELECT {columns} FROM {tableName}"; } private static string GetSelectSqlWithPrimaryKey(Type type) { var tableName = GetTableName(type); var columns = string.Join(", ", GetProperties(type) .Select(p => p.GetCustomAttribute()!.ColumnName)); var primaryKey = GetPrimaryKeyProperties(type); var whereClause = $"{primaryKey.GetCustomAttribute()!.ColumnName} = @{primaryKey.Name}"; return $"SELECT {columns} FROM {tableName} WHERE {whereClause}"; } public void Test() { Console.WriteLine("===========this is a test area================="); Console.WriteLine(GetInsertSql(GetType())); Console.WriteLine(GetDeleteSql(GetType())); Console.WriteLine(GetUpdateSql(GetType())); Console.WriteLine(GetSelectSql(GetType())); Console.WriteLine(GetSelectSqlWithPrimaryKey(GetType())); Console.WriteLine("===========this is a test area================="); } public virtual void Insert() { var type = GetType(); var insertSql = GetInsertSql(GetType()); using MySqlConnection connection = new(GlobalArea.ConnectionStringWithDbName); connection.Open(); // 确保在执行命令之前打开连接 using var command = new MySqlCommand(insertSql, connection); AddParameters(command); Console.WriteLine($"SQL: {command.CommandText}"); foreach (MySqlParameter param in command.Parameters) { Console.WriteLine($"Parameter: {param.ParameterName}, Value: {param.Value}"); } command.ExecuteNonQuery(); Log.Info($"{GetTableName(type)}数据表插入({string.Join(',', ShowDetail())})"); } public virtual void Update() { var type = GetType(); var updateSql = GetUpdateSql(GetType()); using MySqlConnection connection = new(GlobalArea.ConnectionStringWithDbName); connection.Open(); // 确保在执行命令之前打开连接 using var command = new MySqlCommand(updateSql, connection); AddParameters(command); command.ExecuteNonQuery(); Log.Info($"{GetTableName(type)}数据表修改({string.Join(',', ShowDetail())})"); } public virtual void Delete() { var type = GetType(); var deleteSql = GetDeleteSql(GetType()); using MySqlConnection connection = new(GlobalArea.ConnectionStringWithDbName); connection.Open(); // 确保在执行命令之前打开连接 using var command = new MySqlCommand(deleteSql, connection); AddParameters(command); command.ExecuteNonQuery(); Log.Info($"{GetTableName(type)}数据表删除({string.Join(',', ShowDetail())})"); } public static IEnumerable SelectAll() where T : BaseObject, new() { var type = typeof(T); var selectSql = GetSelectSql(type); using MySqlConnection connection = new(GlobalArea.ConnectionStringWithDbName); connection.Open(); // 确保在执行命令之前打开连接 using var command = new MySqlCommand(selectSql, connection); using var reader = command.ExecuteReader(); var results = new List(); while (reader.Read()) { var item = new T(); PopulateObject(reader, item); results.Add(item); } return results; } public static T? Get(object key) where T : BaseObject, new() { var type = typeof(T); var selectSql = GetSelectSqlWithPrimaryKey(type); using MySqlConnection connection = new(GlobalArea.ConnectionStringWithDbName); connection.Open(); // 确保在执行命令之前打开连接 using var command = new MySqlCommand(selectSql, connection); var primaryKey = GetPrimaryKeyProperties(type); command.Parameters.AddWithValue("@" + primaryKey.GetCustomAttribute()!.ColumnName, key); using var reader = command.ExecuteReader(); while (reader.Read()) { var item = new T(); PopulateObject(reader, item); return item; } return null; } private void AddParameters(MySqlCommand command) { foreach (var property in GetProperties(GetType())) { //var columnAttr = property.GetCustomAttribute()!; command.Parameters.AddWithValue("@" + property.Name, property.GetValue(this)); } } private IEnumerable ShowDetail() { return GetProperties(GetType()).Select(p => $"{p.Name}={p.GetValue(this)}"); } private static void PopulateObject(MySqlDataReader reader, BaseObject obj) { var type = obj.GetType(); foreach (var property in GetProperties(type)) { var columnAttr = property.GetCustomAttribute()!; var value = reader[columnAttr.ColumnName]; if (value != DBNull.Value) { property.SetValue(obj, Convert.ChangeType(value, property.PropertyType)); } } } } }