如何在C#中创建一个允许我准备任何插入/更新语句的方法?

时间:2014-07-06 00:29:09

标签: c# mysql prepare

我正在尝试编写一个小类,它将帮助我使用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();

    }

1 个答案:

答案 0 :(得分:1)

您可以让您的方法接受表名和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语法而不是“?”并且参数名称与目标列匹配,无论如何都是更清晰的IMO。