AddWithValue-метод (C #) ничего не делает - PullRequest
2 голосов
/ 14 января 2009

В настоящее время я пишу класс для обработки всей активности базы данных в моем приложении, и поэтому я пришел к методу, который выполняет UPDATE-запросы.

На данный момент я возвращаю и показываю содержимое командного текста, чтобы проверить его, и, кажется, все в порядке:

UPDATE news SET title = @title, newsContent = @newsContent, excerpt = @excerpt, date = @date, urlTitle = @urlTitle, isPublished = @isPublished WHERE (id = @id);

Итак, хорошо, другими словами. Следующим шагом является замена всех @values ​​действительными значениями, и именно здесь я сталкиваюсь с проблемами. Ничего не произошло. Метод AddWithValue, похоже, ничего не делает, и я не вижу причин для этого.

public string updateQuery(string table, string[] fields, object[] values, string conditionField, object conditionValue)
{
    try
    {
        StringBuilder cmd = new StringBuilder("UPDATE " + table + " SET ");

        int i = 1;
        foreach (string s in fields)
        {
            if (i == fields.Length)
            {
                cmd.Append(s + " = @" + s + " ");
            }
            else
            {
                cmd.Append(s + " = @" + s + ", ");
            }

            i++;
        }

        cmd.Append("WHERE (" + conditionField + " = @" + conditionField + ");");
        command.CommandText = cmd.ToString();

        int j = 0;
        foreach (object o in values)
        {
            command.Parameters.AddWithValue("@" + fields[j], o);
            j++;
        }
        command.Parameters.AddWithValue("@" + conditionField, conditionValue);

        command.ExecuteNonQuery();
        connection.Close();

        return command.CommandText;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

Кто-нибудь?

Ответы [ 7 ]

2 голосов
/ 14 января 2009

Что вы подразумеваете под "это ничего не делает"? Вы имеете в виду, что параметры не имеют значений при выполнении команды? Или текст команды остался прежним?

Если это последнее, то это ожидается. Команда не изменяет текст запроса, она отправляет на сервер текст запроса вместе со значениями параметров.

2 голосов
/ 14 января 2009

Спасибо за предложения, Джоэл Коухорн, я их рассмотрю.

Тем не менее, я хочу, чтобы мои вещи заработали: p

Только что заметил, что поле даты фактически обновлялось все время. Ни одно из других полей, хотя. Это просто имеет меньше смысла, чем больше я на это смотрю. Может быть, лучше попробовать утром, чем в полночь.

EDIT: Выяснил, в чем проблема, и все оказалось гораздо проще, чем я ожидал. Я забыл проверить, была ли страница обратной передачей, поэтому каждый раз, когда я обновлял базу данных, поля заполнялись данными из базы данных перед вызовом метода submit. Таким образом, метод обновления работал все время. краснеет

1 голос
/ 14 января 2009

Если вы ожидаете обновления строки, вы будете разочарованы. Важной особенностью использования параметризованного запроса является то, что значения никогда не подставляются непосредственно в командную строку, и, таким образом, вы защищены от такого рода уязвимости безопасности. Вместо этого данные передаются на сервер отдельно.

Позвольте мне предложить эту новую сигнатуру функции:

public string updateQuery(string table, IEnumerable<KeyValuePair<string, object>> values, KeyValuePair<string, object> condition)

Это создаст сильную связь между именами ваших параметров и значениями, а также даст вам гибкость в использовании конструкций, отличных от массива (хотя массив, безусловно, также будет принят). Тогда код будет выглядеть так:

public string updateQuery(string table, IEnumerable<KeyValuePair<string, object>> values, KeyValuePair<string, object> condition)
{
    using (StringBuilder cmd = new StringBuilder("UPDATE [" + table + "]\nSET "))
    {
        string delimiter = "";
        foreach (KeyValuePair<string, object> item in values)
        {
           cmd.AppendFormat("{0}[{1}]=@{1}", delimiter, item.Key);
           delimiter = ",\n";
        }
        cmd.AppendFormat("\nWHERE [{0}]= @{0};", condition.Key);

        command.CommandText = cmd.ToString();
    }

    foreach (KeyValuePair<string, object> item in values)
    {
        command.Parameters.AddWithValue("@" + item.Key, (object)item.Value ?? DBNull.Value);
    }
    command.Parameters.AddWithValue("@" + condition.Key, condition.Value);

    // you didn't show where the connection was created or opened
    command.ExecuteNonQuery();    
    connection.Close();

    return command.CommandText;
}

Еще лучше, если вы можете использовать что-то, что будет создавать строго типизированные параметры базы данных (например, IEnumerable<SqlParameter>).

1 голос
/ 14 января 2009

Потенциально значение идентификатора, которое вы вводите, не соответствует записи в таблице, которую вы обновляете.

Кстати, бросьте попытку ... поймайте, что это не служит никакой цели.

1 голос
/ 14 января 2009

Возможно ли, что значение arg равно нулю? Если так, то параметр не будет добавлен. Для нулей вам необходимо использовать DBNull.Value; например (не единственный способ сделать это):

cmd.Parameters.AddWithValue(argName, (object)argValue ?? DBNull.Value);
0 голосов
/ 14 января 2009

Используя мой другой код, ваш новый метод updatePost будет выглядеть следующим образом.

using DBParam = KeyValuePair<string, object>; // reduce need to keep re-typing this

public void updatePost(int postId)
{   
    List<DBParam> values = new List<DBParam>();

    values.Add(new DBParam("title", this.title));
    values.Add(new DBParam("newsContent", this.content));
    values.Add(new DBParam("excerpt", this.excerpt));
    values.Add(new DBParam("date", this.date));
    values.Add(new DBParam("urlTitle", this.urlTitle));
    values.Add(new DBParam("isPublished", this.isPublished));

    new DbConnection().updateQuery("news", values, new DBParam("id", postid));
}
0 голосов
/ 14 января 2009

Я просто выложу остальную часть кода, я думаю. Сначала метод, который передает значения:

public void updatePost(int postId)
{
    DbConnection d = new DbConnection();

    string[] fields = {
                          "title",
                          "newsContent",
                          "excerpt",
                          "date",
                          "urlTitle",
                          "isPublished" 
                      };

    object[] values = {
                          this.title,
                          this.content,
                          this.excerpt,
                          this.date,
                          this.urlTitle,
                          this.isPublished,
                      };

    d.updateQuery("news",fields,values,"id",postId);
}

Метод конструктора, который подключается к базе данных:

public DbConnection()
{        
    connection = new SqlConnection("Data Source=****; User Id=****; Password=*****;");
    connection.Open();
    command = connection.CreateCommand();
}

Мне еще предстоит выяснить проблему, но я действительно ценю любую помощь, которую я получаю в любом случае. : -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...