Коллекция OdbcParameterCollection принимает только ненулевые объекты типа OdbcParameter.

Небольшое предупреждение: я совершенно новичок во всей этой «кодировке» в целом, поэтому простите меня, если я неясно выражаюсь, и просто дайте мне знать, если я могу сказать вам что-нибудь еще. Я гуглил несколько дней и ничего не мог найти, я не уверен, что это плохо с моей стороны, или просто потому, что я действительно новичок и не знал бы решения, если бы оно было прямо перед моими глазами. лицо.

Когда я иду тестировать приложение (Visual Studio 2010), все отображается, и я могу вводить информацию в свои текстовые поля, но как только я нажимаю «Отправить», появляется эта ошибка:

«Коллекция OdbcParameterCollection принимает только ненулевые объекты типа OdbcParameter. Имя параметра: значение»

и указывает на эту строку кода:

cmd.Parameters.Add(pram[i]);

Я не знаю, неправильно ли я устанавливаю параметры или оператор INSERT INTO или что-то еще. Я также могу показать вам код ASP.net, если это необходимо. Дайте мне знать, если я могу дать вам больше информации! Заранее благодарю!

Мой код С# таков:

 private void execution(string eventspecialist, string phone, string phone2, string firstname, string lastname, string besttime, string companyname, string nonprofit, string requesteddate, string requestedtime, string attendance, string eventtype, string other, string leadsource, string notes, string catering, string bar, string damagedeposit, string dancefloor)
{


    OdbcConnection conn = new OdbcConnection(GetConnectionString());

    string sql = "INSERT INTO tblcontacts (eventspecialist, phone, phone2, firstname, lastname, besttime, companyname, nonprofit, requesteddate, requestedtime, attendance, eventtype, other, leadsource, notes, catering, bar, damagedeposit, dancefloor) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

    try
    {
        conn.Open();
        OdbcCommand cmd = new OdbcCommand(sql, conn);

        cmd.Parameters.Add("@SPECIALIST", OdbcType.NVarChar, 50).Value = eventspecialist;
        cmd.Parameters.Add("@CUST_PHONE1", OdbcType.NVarChar, 50).Value = phone;
        cmd.Parameters.Add("@CUST_PHONE2", OdbcType.NVarChar, 50).Value = phone2;
        cmd.Parameters.Add("@CUST_FNAME", OdbcType.NVarChar, 50).Value = firstname;
        cmd.Parameters.Add("@CUST_LNAME", OdbcType.NVarChar, 50).Value = lastname;
        cmd.Parameters.Add("@BEST_TIME", OdbcType.NVarChar, 50).Value = besttime;
        cmd.Parameters.Add("@COMPANY_NAME", OdbcType.NVarChar, 225).Value = companyname;
        cmd.Parameters.Add("@NONPROFIT", OdbcType.NVarChar, 1).Value = nonprofit;
        cmd.Parameters.Add("@REQ_DATE", OdbcType.NVarChar, 10).Value = requesteddate;
        cmd.Parameters.Add("@REQ_TIME", OdbcType.NVarChar, 20).Value = requestedtime;
        cmd.Parameters.Add("@ATTENDANCE", OdbcType.NVarChar, 50).Value = attendance;
        cmd.Parameters.Add("@EVENT_TYPE", OdbcType.NVarChar, 50).Value = eventtype;
        cmd.Parameters.Add("@OTHER_DESC", OdbcType.NVarChar, 225).Value = other;
        cmd.Parameters.Add("@LEAD_SOURCE", OdbcType.NVarChar, 50).Value = leadsource;
        cmd.Parameters.Add("@NOTES", OdbcType.NVarChar, 225).Value = notes;
        cmd.Parameters.Add("@CATERING", OdbcType.NVarChar, 1).Value = catering;
        cmd.Parameters.Add("@BAR", OdbcType.NVarChar, 1).Value = bar;
        cmd.Parameters.Add("@DAMAGE_DEPOSIT", OdbcType.NVarChar, 19).Value = damagedeposit;
        cmd.Parameters.Add("@DANCE_FLOOR", OdbcType.NVarChar, 19).Value = dancefloor;



        cmd.CommandType = CommandType.Text;
        cmd.ExecuteNonQuery();
    }
    catch (System.Data.Odbc.OdbcException ex_msg)
    {

        string msg = "Error occured while inserting";
        msg += ex_msg.Message;
        throw new Exception(msg);
    }
    finally
    {

        conn.Close();
    }
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void submit_Click(object sender, EventArgs e)
{
    execution(eventspecialist.Text, phone.Text, phone2.Text, firstname.Text, lastname.Text, besttime.SelectedItem.Text, companyname.Text, nonprofit.Text, requesteddate.Text, requestedtime.Text, attendance.Text, eventtype.SelectedItem.Text, other.Text, leadsource.SelectedItem.Text, notes.Text, catering.Text, bar.Text, damagedeposit.Text, dancefloor.SelectedItem.Text);

    conform.Visible = true;
    Control frm = this.FindControl("form1");
    foreach (Control ctrl in frm.Controls)
    {
        if (ctrl is TextBox)
        {
            ((TextBox)ctrl).Text = "";
        }
        else if (ctrl is CheckBox)
        {
            ((CheckBox)ctrl).Checked = false;
        }
        else if (ctrl is DropDownList)
        {
            ((DropDownList)ctrl).SelectedIndex = 0;
        }
    }
}

person Control    schedule 25.01.2012    source источник
comment
какой сервер базы данных вы используете mysql???   -  person Devjosh    schedule 25.01.2012
comment
Я использую источник данных ODBC для собственного клиента SQL Server 10.0. Если это то, о чем вы спрашивали?   -  person Control    schedule 25.01.2012
comment
Почему вы не используете SqlClient? msdn.microsoft.com/en-us/library/system. data.sqlclient.aspx msdn.microsoft .com/en-us/library/   -  person Lloyd    schedule 25.01.2012
comment
Потому что всякий раз, когда я использовал это, это выдавало мне ошибку, в которой говорилось, что ключевое слово «dsn» не поддерживается, что после поиска в Интернете кто-то рекомендовал вместо этого использовать ODBC. Не уверен, что это было мудрое решение.   -  person Control    schedule 25.01.2012


Ответы (4)


Вы получаете нулевую ссылку, потому что вы создали и установили размер pram, но не добавили к нему никаких объектов. Итак, у вас есть массив, заполненный нулями. Похоже, вы можете полностью исключить цикл for и массив pram, потому что вы уже добавляете параметры в cmd вне цикла.

Следующий код не нужен:

OdbcParameter[] pram = new OdbcParameter[19];

а также

for (int i = 0; i < pram.Length; i++)
{
    cmd.Parameters.Add(pram[i]);
}

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

cmd.Parameters.Add("@SPECIALIST", OdbcType.NVarChar, 50).Value = eventspecialist;

Итак, ваш блок try будет выглядеть так:

try
{
    conn.Open();
    OdbcCommand cmd = new OdbcCommand(sql, conn);

    cmd.Parameters.Add("@SPECIALIST", OdbcType.NVarChar, 50).Value = eventspecialist;
    cmd.Parameters.Add("@CUST_PHONE1", OdbcType.NVarChar, 50).Value = phone;
    cmd.Parameters.Add("@CUST_PHONE2", OdbcType.NVarChar, 50).Value = phone2;
    cmd.Parameters.Add("@CUST_FNAME", OdbcType.NVarChar, 50).Value = firstname;
    cmd.Parameters.Add("@CUST_LNAME", OdbcType.NVarChar, 50).Value = lastname;
    cmd.Parameters.Add("@BEST_TIME", OdbcType.NVarChar, 50).Value = besttime;
    cmd.Parameters.Add("@COMPANY_NAME", OdbcType.NVarChar, 225).Value = companyname;
    cmd.Parameters.Add("@NONPROFIT", OdbcType.NVarChar, 1).Value = nonprofit;
    cmd.Parameters.Add("@REQ_DATE", OdbcType.Date, 10).Value = requesteddate;
    cmd.Parameters.Add("@REQ_TIME", OdbcType.Time, 20).Value = requestedtime;
    cmd.Parameters.Add("@ATTENDANCE", OdbcType.NVarChar, 50).Value = attendance;
    cmd.Parameters.Add("@EVENT_TYPE", OdbcType.NVarChar, 50).Value = eventtype;
    cmd.Parameters.Add("@OTHER_DESC", OdbcType.NVarChar, 225).Value = other;
    cmd.Parameters.Add("@LEAD_SOURCE", OdbcType.NVarChar, 50).Value = leadsource;
    cmd.Parameters.Add("@NOTES", OdbcType.NVarChar, 225).Value = notes;
    cmd.Parameters.Add("@CATERING", OdbcType.NVarChar, 1).Value = catering;
    cmd.Parameters.Add("@BAR", OdbcType.NVarChar, 1).Value = bar;
    cmd.Parameters.Add("@DAMAGE_DEPOSIT", OdbcType.NVarChar, 19).Value = damagedeposit;
    cmd.Parameters.Add("@DANCE_FLOOR", OdbcType.NVarChar, 19).Value = dancefloor;

    cmd.CommandType = CommandType.Text;
    cmd.ExecuteNonQuery();

}

Из редактирования вашего вопроса я вижу, что это код, который вы используете, и я так понимаю, вы все еще получаете ту же ошибку? Скорее всего, это означает, что одно из значений, которые вы добавляете в коллекцию параметров, равно null. Если вы проверите их с помощью отладчика, все ли они имеют установленные значения?

Редактировать, еще раз:

Есть еще одна ошибка, которую я пропустил раньше. Команда SQL, которую вы написали для ODBC, неправильно использует параметры, на что указывает новая ошибка.

string sql = "INSERT INTO tblcontacts (eventspecialist, phone, phone2, firstname, lastname, besttime, companyname, nonprofit, requesteddate, requestedtime, attendance, eventtype, other, leadsource, notes, catering, bar, damagedeposit, dancefloor) 
VALUES (@SPECIALIST, @CUST_PHONE1, @CUST_PHONE2, @CUST_FNAME, @CUST_LNAME, @BEST_TIME, @COMPANY_NAME, @NONPROFIT, @REQ_DATE, @REQ_TIME, @ATTENDANCE, @EVENT_TYPE, @OTHER_DESC, @LEAD_SOURCE, @NOTES, @CATERING, @BAR, @DAMAGE_DEPOSIT, @DANCE_FLOOR)";

Должно быть:

string sql = "INSERT INTO tblcontacts (eventspecialist, phone, phone2, firstname, lastname, besttime, companyname, nonprofit, requesteddate, requestedtime, attendance, eventtype, other, leadsource, notes, catering, bar, damagedeposit, dancefloor) 
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

Обратите внимание, что я разбил строку кода для удобства чтения. Кроме того, порядок добавления параметров в коллекцию имеет значение. Они должны быть в порядке, соответствующем столбцам (значение для eventspecialist должно быть первым, значение для phon вторым и т. д.). Также может быть случай, когда вам нужно назвать свои параметры так же, как имена столбцов, как @shahkalpesh предлагает.

Команды ODBC используют ? для доступа к параметрам, а не имя параметра, как это делают команды SQL. Пара ссылок по теме:

http://msdn.microsoft.com/en-us/library/yy6y35y8.aspx

http://msdn.microsoft.com/en-us/library/8dcw81x5.aspx

Изменить

Я заметил, что вы передаете все значения методу как string. Вам нужно будет преобразовать их в правильный тип и использовать правильный тип данных ODBC при добавлении параметров. См. эту ссылку для типов параметров ODBC.

Используйте любой тип столбца (varchar, money и т. д.), и если ваши переменные (eventspecialist и т. д.) имеют неправильный тип, преобразуйте значения в правильный тип (как указано в ссылке) перед их добавлением. Например, cmd.Parameters.Add("@ATTENDANCE", OdbcType.Int).Value = Int32.Parse(attendance);. Обратите внимание, что Int32.Parse может вызвать ошибку, если attendance не является строкой, представляющей целое число. Я предлагаю изменить сигнатуру метода, чтобы она требовала правильных типов, а затем проверять и преобразовывать их перед вызовом execution. Это позволит избежать ошибок преобразования типов в этом методе. Таким образом, если вы получите здесь ошибку, вы будете знать, что она связана с взаимодействием с БД, а не с неправильной настройкой команды.

person Esoteric Screen Name    schedule 25.01.2012
comment
Итак, чтобы убедиться, вы имеете в виду удаление for (int i = 0; i ‹ pram.Length; i++) { cmd.Parameters.Add(pram[i]); } и что еще? - person Control; 25.01.2012
comment
Да, вы можете удалить весь цикл for. Поскольку вы ничего не поместили в массив коляски, вы ничего не получите из него, и именно отсюда берется нулевое значение. Но поскольку вы вручную добавляете параметры в команду (cmd.Parameters.Add(...); и cmd.Parameters[xxx].Value = xxx;), вам не нужно добавлять их снова. Вы также можете удалить строку OdbcParameter[] pram = new OdbcParameter[19]; Я отредактировал свой ответ, чтобы быть более понятным. - person Esoteric Screen Name; 25.01.2012
comment
@Kruce: удалите OdbcParameter[] и все его использование. Вместо этого используйте .Value = x. - person abatishchev; 25.01.2012
comment
Где бы я разместил .Value = x, где бы ни находился OdbcParameter[]? Так, например, .Value pram = new .Value = 19? Или это просто шло в совершенно неправильном направлении? - person Control; 25.01.2012
comment
Вы бы добавили .Value = x к каждой cmd.Parameters.Add(...); строке и удалили каждую cmd.Parameters["@x"].Value = x; строку. Я отредактирую свой ответ с полным примером. - person Esoteric Screen Name; 25.01.2012
comment
О, я понимаю, что вы имеете в виду. Я сделал это и отредактировал свой код сейчас, я просто получаю эту ошибку: Произошла ошибка при вставке ERROR [42000] [Microsoft] [SQL Server Native Client 10.0] [SQL Server] Должен объявить скалярную переменную @SPECIALIST. - person Control; 25.01.2012
comment
@Kruce: Я предполагаю, что для начала вам придется назвать параметры так же, как имя столбца. Пожалуйста, посмотрите на ответ, я написал выше. - person shahkalpeshp; 25.01.2012
comment
Вы имеете в виду пример, который показывает: cmd.Parameters.Add(eventspecialist, OdbcType.NVarChar, 50); Я это понимаю, но как мне связать это с моей фактической базой данных @SPECIALIST? - person Control; 25.01.2012
comment
@Kruce Я обновил свой ответ, чтобы устранить новую ошибку, которую вы получаете. - person Esoteric Screen Name; 25.01.2012
comment
Изначально у меня были ?, ?, ?, ? и т. д., но они изменились в зависимости от ответов. Я считаю, что все в правильном порядке. Я получаю новую ошибку: ОШИБКА [42S22] Недопустимое имя столбца «специалист по событию». Это повторяется и для всех остальных. Итак, когда вы говорите, что мои параметры называются так же, как у столбца, вы предлагаете переименовать специалиста по событиям в SPECILAIST? - person Control; 25.01.2012
comment
Придерживайтесь использования ?. Отсутствие этого вызывало ошибку Must declare the scalar variable "@SPECIALIST". Как выглядит ваше определение таблицы? Эта ошибка предполагает, что в таблице tblcontacts нет столбца с именем eventspecialist. Я считаю, что предложение Шахкалпеша состоит в том, чтобы изменить @SPECIALIST на eventspecialist в строке cmd.Parameters.Add(@SPECIALIST, ... - person Esoteric Screen Name; 25.01.2012
comment
Нет, имя столбца моей таблицы — СПЕЦИАЛИСТ, «специалист по событиям» — это имя текстового поля, в которое пользователь помещает информацию, которую я хочу отправить в свою таблицу. Я делаю это совершенно неправильно? - person Control; 25.01.2012
comment
@Kruce - ах, да. Вы должны использовать имена столбцов, а не имена текстовых полей. Так и должно быть string sql = "INSERT INTO tblcontacts (SPECIALIST, ... - person Esoteric Screen Name; 25.01.2012
comment
Ах, я думаю, что, возможно, только что сделал это. Теперь я получаю небольшие ошибки, такие как Не удалось преобразовать значение параметра из строки в десятичное число. Но я считаю, что это потому, что я объявляю все как NVarChar, когда некоторые вещи являются числовыми или деньгами. У вас есть какие-либо предложения по этому поводу, пока я все еще в вашей помощи? Также спасибо за терпение. - person Control; 25.01.2012
comment
@Kruce Я обновляю свой ответ. - person Esoteric Screen Name; 25.01.2012
comment
Спасибо! Это было очень, очень полезно. Как я уже говорил, я новичок во всем этом, так что у вас есть простой способ объяснить, как на самом деле преобразовать в правильный тип или изменить сигнатуру метода, чтобы потребовать правильные типы, а затем проверить и преобразовать их перед вызовом исполнение. Серьезно еще раз, спасибо за помощь. Я не хочу, чтобы вы чувствовали, что вам нужно нянчиться со мной через все это, но любая помощь чрезвычайно ценна. :) - person Control; 25.01.2012
comment
Кроме того, DANCE_FLOOR — это деньги, но это не ODBC.Type? - person Control; 25.01.2012
comment
Нет проблем, все когда-то были новичками. Я бы попробовал decimal для типа ODBC для параметра DANCE_FLOOR. Проверьте: msdn.microsoft.com/en-us/library/ms173105.aspx для краткого изложения основ преобразования ваших строк в соответствующие типы. На данный момент я бы просто конвертировал их внутри метода execution. Как только все заработает, переместите преобразования наружу, чтобы улучшить структуру, и измените метод на execute(string eventspecialist, ... , decimal dancefloor, etc). - person Esoteric Screen Name; 25.01.2012
comment
О боже, это совсем другая проблема, над которой мне придется поработать! Смешной! Спасибо за помощь всем в этом вопросе и эзотерике. Я ценю его! - person Control; 25.01.2012

Ошибка в том, что вы определили массив (OdbcParameter[] pram = new OdbcParameter[19];). Но вы не инициализируете его элементы.

Глядя на ваш код, следующие строки в вашем коде не требуются.

OdbcParameter[] pram = new OdbcParameter[19];

и

for (int i = 0; i < pram.Length; i++)
{
    cmd.Parameters.Add(pram[i]);
}

EDIT: я не использовал классы Odbc* в прошлом.
Глядя на конкретный пример здесь, имя вашего параметра должно совпадать с именем вашего столбца

cmd.Parameters.Add("eventspecialist", OdbcType.NVarChar, 50);
cmd.Parameters.Add("phone", OdbcType.NVarChar, 50);
cmd.Parameters.Add("phone2", OdbcType.NVarChar, 50);
cmd.Parameters.Add("firstname", OdbcType.NVarChar, 50);
cmd.Parameters.Add("lastname", OdbcType.NVarChar, 50);
cmd.Parameters.Add("besttime", OdbcType.NVarChar, 50);

и так далее по остальным параметрам.

person shahkalpeshp    schedule 25.01.2012

зачем вы это делаете, если вы уже добавили параметры в объект команды.

for (int i = 0; i < pram.Length; i++)
{
    cmd.Parameters.Add(pram[i]);
}

нет необходимости это делать снова, а также изменить

string sql = "INSERT INTO tblcontacts (eventspecialist) VALUES (@SPECIALIST)"

таким образом.

person Ravi    schedule 25.01.2012

Добавьте параметр с определенным значением, предполагая, что значения, которые вы передаете, не равны нулю, если они не указаны.

В зависимости от базы данных имена параметров в вашем запросе должны совпадать с именами параметров, определенными в коллекции OdbcParameters, а в некоторых случаях быть в правильном порядке или приложении.

В соответствии с вашим обновлением укажите имена параметров в вашем запросе.

string sql = "INSERT INTO tblcontacts (eventspecialist, phone, phone2, firstname, lastname, besttime, companyname, nonprofit, requesteddate, requestedtime, attendance, eventtype, other, leadsource, notes, catering, bar, damagedeposit, dancefloor) VALUES (@EVENTSPECIALIST, @CUST_PHONE1, ETC ETC ETC)"; 


// Remove this code.
OdbcParameter[] pram = new OdbcParameter[19]; 

for (int i = 0; i < pram.Length; i++) 
    { 
        cmd.Parameters.Add(pram[i]); 
    } 


// Add your parameters with a value.
cmd.Parameters.Add("@SPECIALIST", OdbcType.NVarChar, 50).Value = eventSpecialist;

Я бы также рекомендовал использовать один из классов подключения к собственной базе данных, где это применимо, System.Data.SqlClient, MySql.Data.Client или клиент Oracle.

person Lloyd    schedule 25.01.2012
comment
@Esoteric Screen Name, почему бы вам не добавить полный разумный ответ вместо комментариев. - person Lloyd; 25.01.2012
comment
@Esoter: Пожалуйста, будьте более дружелюбны на SO - person abatishchev; 25.01.2012
comment
Я сделал это, но получил другую ошибку. Ошибка при вставке ERROR [42000] [Microsoft] [SQL Server Native Client 10.0] [SQL Server] необходимо объявить скалярную переменную @SPECIALIST. Может быть, это потому, что я должен переключать параметры? Я имею в виду, что eventspecialist — это строка в моем коде asp.net, а SPECIALIST — это имя базы данных, к которому я хочу привязать это текстовое поле. - person Control; 25.01.2012
comment
Опять же, искренне простите меня, если я вообще ничего не понимаю, потому что я могу говорить все это неправильно. Я ценю любую форму помощи, которую любой может оказать. - person Control; 25.01.2012
comment
Можете ли вы обновить свой код в вопросе, чтобы мы могли увидеть, что вы сделали? - person Lloyd; 25.01.2012
comment
Я только что обновил то, что я изменил, основываясь на том, что все сказали. Дай мне знать, если увидишь что-нибудь. - person Control; 25.01.2012