可重复使用的数据库更新方法

问题描述 投票:0回答:1

我有一个可以在不同实例中使用的方法来更新表。

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;

            }
        }

此处不应更新 ORDER_NUMBER。因此我必须这样省略 ORDER_NUMBER 。好吧,如果我这样做,我将无法在不同的情况下使用此方法。如果我要使此方法可在多个实例上重用,特别是在一个实例上,如果我要使用此方法,则需要专家的建议,以一种不应更新 ORDER_NUMBER 字段的方式。我怎样才能做到这一点?以下是我在 main 方法中使用该方法的方式。

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,我已将其省略。更新值时,该方法应避免更新 ORDER_NUMBER 并且不更改其值。由于我正在创建模型的新实例,ORDER_NUMBER 变为空,并且在更新时插入 ORDER_NUMBER 的空值,这将替换已经存在的 ORDER_NUMBER 值而不是避免。 我提供的代码片段是.net wpf c#,遵循 MVVM 架构模式。我正在将值插入 MySQL 数据库。

c# mysql .net wpf mvvm
1个回答
0
投票

简短回答:如果您不希望更改模型中的值,请不要公开设置器。如果该值类似于数据库中的“计算”列或“标识”列,则使用属性上的属性来告诉迭代反射属性的代码要忽略哪些内容。即

[DatabaseGemerated(DatabaseGeneratedOption.Computed)] // or DatabaseGeneratedOption.Identity
public int Order_Number { get; private set; }

更简短的答案:使用实体框架。 EF 管理所有这些,并且比您自己编写的内容还要多。 (EF 使用上例中的属性)EF 的更改跟踪器还支持只读字段。如果您未公开公共 setter,则 Order_Number 无法更改,并且任何生成的 UPDATE sql 语句甚至不会包含它。 UPDATE 语句是针对实际更改的值生成的,并且仅当任何值已更改时才生成。

© www.soinside.com 2019 - 2024. All rights reserved.