You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:40:17