我正试图写一个小类,将帮助我使用c#和winforms连接到MySQL服务器。我编写了启动和关闭连接的连接。
我在这里要做的是在这个类中创建一个方法,允许我传递一个查询和值"在数组中",该方法将自动为我准备查询。
所以不是为每个INSERT/UPDATE查询写一个方法或代码,像这样…
MySqlCommand command = connection.CreateCommand();
command.CommandText = "INSERT INTO mytable(a,b,c,d)VALUES (?, ?, ?, ?)";
command.Parameters.AddWithValue("?", array_val1);
command.Parameters.AddWithValue("?", array_val2);
command.Parameters.AddWithValue("?", array_val3);
command.Parameters.AddWithValue("?", array_val4);
connection.Open();
command.ExecuteNonQuery();
我想有一个方法,我可以传递查询和值,它会自动为我准备语句。
像这样的
//Call the Method
processQuery("INSERT INTO mytable(a,b,c,d)VALUES (?, ?, ?, ?)", array(1,2,3,4));
//The new Method
public processQuery(string sqlStr, array values){
MySqlCommand command = connection.CreateCommand();
command.CommandText = sqlStr;
command.Parameters.AddWithValue("?", array_val1);
command.Parameters.AddWithValue("?", array_val2);
command.Parameters.AddWithValue("?", array_val3);
....
....
....
....
command.Parameters.AddWithValue("?", array_val_SIZE_OF_ARRAY);
connection.Open();
command.ExecuteNonQuery();
}
你可以让你的方法接受一个表名和一个MySqlParameter列表,然后根据你传递的内容制作你的SQL。
public void ProcessQuery(string tableName, MySqlParameter keyParam, params MySqlParameter[] sqlParams)
{
using(MySqlConnection cn = new MySqlConnection(this.ConnectionString))
using(MySqlCommand cmd = cn.CreateCommand())
{
/*Update Statement*/
//Param1 = @Param1, Param2 = @Param2, @Param3 = @Param3, etc.
string updateParamStr = string.Join(
", ",
sqlParams.Select(sqlParam => string.Format("{0} = {1}", sqlParam.ParameterName.Substring(1), sqlParam.ParameterName)));
//param = @param
string keyMatchStr = string.Format("{0} = {1}",
keyParam.ParameterName.Substring(1),
keyParam.ParameterName);
string updateSql = string.Format("UPDATE {0} SET {1} WHERE {2}",
tableName,
updateParamStr,
keyMatchStr);
/*Insert Statement*/
//produce comma delimited list of param names with leading @ stripped eg. Param1, Param2, Param3
string columnNameStr = string.Join(", ", sqlParams.Select(sqlParam => sqlParam.ParameterName.Substring(1)));
//produce comma delimited list of param eg. @Param1, @Param2, @Param3
string valueParamStr = string.Join(", ", sqlParams.Select(sqlParam => sqlParam.ParameterName));
string insertSql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})",
tableName,
columnNameStr,
valueParamStr);
/*Combined Update and Insert*/
string combinedSql = string.Format("{0} {1} WHERE ROW_COUNT() = 0", updateSql, insertSql);
cmd.CommandText = combinedSql;
cmd.Parameters.Add(keyParam);
cmd.Parameters.AddRange(sqlParams);
cn.Open();
cmd.ExecuteNonQuery();
}
}
生成的SQL创建了一个合并的UPDATE和INSERT语句,看起来像这样:
UPDATE MyTable SET Col1 = @Col1, Col2 = @Col2 WHERE KeyCol = @KeyCol
INSERT INTO MyTable (Col1, Col2) VALUES (@Col1, @Col2) WHERE ROW_COUNT() = 0
这有效地运行UPDATE,要么更新匹配行,要么不更改任何内容。在后一种情况下,ROW_COUNT()将= 0,然后使INSERT语句完成它的工作。我们只是利用每个语句中的WHERE子句使事物互斥。
你可以调用这个方法,传递一个MySqlParameter作为唯一的键,然后尽可能多的MySqlParameter对象。
ProcessQuery(
"MyTable",
new MySqlParameter("@MyKeyColumn", 5)/*unique key column*/,
new MySqlParameter("@SomeColumn", 1),
new MySqlParameter("@SomeOtherColumn", "Some string"));
这样做的好处是允许您在MySqlParameter中提供数据类型信息,如果您选择这样做,或者您可以使用名称+值对保持简单。这确实需要使用@ParamName语法而不是"?",并且参数名称与目标列相匹配,这无论如何都更清晰。