.NET WPF C#通用数据库更新方法复用优化咨询
优化可复用的MySQL表更新方法,支持灵活排除字段
我有一个可跨不同实例复用的数据库表更新方法,但目前硬编码排除了ORDER_NUMBER字段,导致无法在多实例中灵活指定不更新的字段。当前基于.NET WPF C#、MVVM架构操作MySQL,以下是现有代码:
现有更新方法代码
public async Task<bool> UpdateValues(string tableName, string keyColumn, string key, object model) { var columnValues = new Dictionary<string, object>(); var properties = model.GetType().GetProperties(); foreach(var prop in properties) { var value = prop.GetValue(model); if (prop.Name != "ORDER_NUMBER") { columnValues.Add(prop.Name.ToLower(), value ?? DBNull.Value); } } var setClauses = new List<string>(); foreach(var column in columnValues.Keys) { setClauses.Add($"{column} = @{column}"); } string setClause = string.Join(",", setClauses); string query = $"UPDATE {tableName} SET {setClause} WHERE {keyColumn} = @key"; using (var command = new MySqlCommand(query, connection)) { command.Parameters.AddWithValue("@key", key); foreach(var column in columnValues) { command.Parameters.AddWithValue($"@{column.Key}", column.Value); } if(connection.State != ConnectionState.Open) { await connection.OpenAsync(); } int rowsAffected = await command.ExecuteNonQueryAsync(); if(rowsAffected > 0) { MessageBox.Show("Success! Details have been UPDATED."); return true; } return false; } }
调用代码
private async void Submit() { string tableName = "tableName"; string keyColumn = "unique_number"; var columns = new List<string> { "Id", "delivered_date" }; var result = await _db.ReadValues(tableName, keyColumn, SerialNumber, columns); if (result.Count > 0) { string id = result["Id"].ToString(); DateTime deliveredDate; DateTime.TryParse(result["delivered_date"].ToString(), out deliveredDate); if(deliveredDate == DateTime.MinValue) { //var infoToUpdate = new InfoModel //{ // Unique_Id = _infoModel.Unique_Id, // Web_Login = _infoModel.Web_Login, // IMEI = _infoModel.IMEI, // MAC = _infoModel.MAC, //}; await _db.UpdateValues(tableName, "Id", id, _deviceInfo); } else { await _db.InsertValues(tableName, _deviceInfo); } } else { await _db.InsertValues(tableName, _deviceInfo); } }
问题点:硬编码排除ORDER_NUMBER字段,无法灵活适配不同实例的排除需求;如果新建模型时包含该字段,null值会覆盖数据库已有值,而非跳过更新。
优化方案
1. 修改UpdateValues方法参数,添加排除字段列表
给方法增加一个可选参数,接收需要排除的字段集合,默认值为空列表,不影响原有调用逻辑:
public async Task<bool> UpdateValues(string tableName, string keyColumn, string key, object model, List<string> excludedColumns = null) { // 初始化排除字段列表,默认空集合 excludedColumns ??= new List<string>(); var columnValues = new Dictionary<string, object>(); var properties = model.GetType().GetProperties(); foreach(var prop in properties) { var value = prop.GetValue(model); // 忽略大小写匹配,适配模型属性与数据库字段的大小写差异 if (!excludedColumns.Any(col => string.Equals(col, prop.Name, StringComparison.OrdinalIgnoreCase))) { columnValues.Add(prop.Name.ToLower(), value ?? DBNull.Value); } } var setClauses = new List<string>(); foreach(var column in columnValues.Keys) { setClauses.Add($"{column} = @{column}"); } string setClause = string.Join(",", setClauses); string query = $"UPDATE {tableName} SET {setClause} WHERE {keyColumn} = @key"; using (var command = new MySqlCommand(query, connection)) { command.Parameters.AddWithValue("@key", key); foreach(var column in columnValues) { command.Parameters.AddWithValue($"@{column.Key}", column.Value); } if(connection.State != ConnectionState.Open) { await connection.OpenAsync(); } int rowsAffected = await command.ExecuteNonQueryAsync(); if(rowsAffected > 0) { MessageBox.Show("Success! Details have been UPDATED."); return true; } return false; } }
2. 调用时灵活指定排除字段
在Submit方法中调用更新时,按需传入需要排除的字段:
if(deliveredDate == DateTime.MinValue) { // 指定当前实例需要排除的字段 var excludedFields = new List<string> { "ORDER_NUMBER" }; await _db.UpdateValues(tableName, "Id", id, _deviceInfo, excludedFields); }
3. 额外优化建议
- 移除UI层耦合:
MessageBox.Show属于UI逻辑,放在数据访问层不符合MVVM架构,建议将操作结果返回给ViewModel,由ViewModel处理提示; - 参数类型优化:替换
AddWithValue为指定参数类型的MySqlParameter构造函数,避免类型推断问题; - 字段映射校验:增加模型属性与数据库字段的映射校验,防止因字段名不匹配导致的更新失败;
- 空值校验:针对数据库非空字段,在遍历属性时增加空值判断,避免传入无效值。
内容的提问来源于stack exchange,提问作者joekevinrayan96
相关产品推荐
相关产品推荐

