我有一个可以在不同实例中使用的方法来更新表。
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 数据库。
简短回答:如果您不希望更改模型中的值,请不要公开设置器。如果该值类似于数据库中的“计算”列或“标识”列,则使用属性上的属性来告诉迭代反射属性的代码要忽略哪些内容。即
[DatabaseGemerated(DatabaseGeneratedOption.Computed)] // or DatabaseGeneratedOption.Identity
public int Order_Number { get; private set; }
更简短的答案:使用实体框架。 EF 管理所有这些,并且比您自己编写的内容还要多。 (EF 使用上例中的属性)EF 的更改跟踪器还支持只读字段。如果您未公开公共 setter,则 Order_Number 无法更改,并且任何生成的 UPDATE sql 语句甚至不会包含它。 UPDATE 语句是针对实际更改的值生成的,并且仅当任何值已更改时才生成。