#c# #sql
#c# #sql
Вопрос:
У меня возникли проблемы с моей программой для работы. Все построено успешно, но при отладке я получил исключение index out of range в TotalUnits = Convert.ToDouble(значения [1].toString());. Предполагается, что программа вычисляет формулу и возвращает значение в текстовое поле. Я так запутался. Кто-нибудь, пожалуйста, может мне помочь? Спасибо.
Джастин
Вот некоторые из моего кода для просмотра:
private double GetRefurbRate()
{
string sql = "";
double Refurb_Rate = 0;
double totalRefurb = 0;
double totalUnits = 0;
string error_msg = "";
//Getting the value for sql for totalRefurb
sql = "SELECT COUNT(distinct rp.repair_ord) "
"FROM " schema ".repair_part rp "
"WHERE rp.repair_type = 'REFURB' and rp.created_date > '" DateTime.Now.ToString("d-MMM-yyyy") "' ";
while (true)
{
if (!myDb.RunSql(sql, true))
{
error_msg = "DBError for getting Refurb Rate";
break;
}
if (myDb.dbRdr.HasRows)
{
if (myDb.dbRdr.Read())
{
object[] values = new object[myDb.dbRdr.FieldCount];
myDb.dbRdr.GetValues(values);
Console.WriteLine(values[0].ToString());
totalRefurb = Convert.ToDouble(values[0].ToString());
//Getting the value from sql for totalUnits
sql = "SELECT count(distinct rp.repair_ord) "
"FROM " schema ".repair_part rp "
"WHERE rp.repair_type = 'REFURB' and rp.ref_desig is null and rp.created_date > '" DateTime.Now.ToString("d-MMM-yyyy") "' ";
while (true)
{
if (!myDb.RunSql(sql, true))
{
error_msg = "DBError for getting Refurb Rate";
break;
}
if (myDb.dbRdr.HasRows)
{
if (myDb.dbRdr.Read())
{
values = new object[myDb.dbRdr.FieldCount];
myDb.dbRdr.GetValues(values);
Console.WriteLine(values[1].ToString());
totalUnits = Convert.ToDouble(values[1].ToString());
try
{
//Formula for Refurb Rate
Refurb_Rate = totalRefurb / totalUnits * 100;
break;
}
catch (Exception e)
{
Console.WriteLine(e);
}
myDb.dbRdr.Close();
if (error_msg != String.Empty)
{
MessageBox.Show(error_msg, "Get Refurb Rate",
MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
break;
}
}
}
}
}
}
return Refurb_Rate;
}
Комментарии:
1. Не имеет отношения к вашему вопросу, но, пожалуйста, обратите внимание: построение SQL-запросов с помощью конкатенации строк действительно плохо . Это приводит к уязвимостям SQL-инъекций. Посмотрите на использование параметризованных запросов.
Ответ №1:
Вы должны убедиться, что оно values[1]
существует и что его можно преобразовать в double.
Кроме того, если объект является double , вам не нужно его преобразовывать, просто используйте приведение ( (double)values[1]
или values[1] as double
).
Я не знаю, должен ли я сообщать, но на всякий случай массивы основаны на нуле, что означает, что если вы хотите сослаться на первый элемент в массиве, вы должны вы values[0]
вместо values[1]
. извините, если в этом не было необходимости.
Вам также следует пересмотреть удаление while (true)
, если есть более простой способ сделать это, если вы не ожидаете неожиданного подсчета.
В вашем вопросе оба запроса возвращают только одно поле данных, и, следовательно, вы должны использовать values[0]
в обоих случаях.
Комментарии:
1. Я не настолько опытен в программировании, поэтому любая информация хороша
Ответ №2:
Сначала вы должны проверить длину значений, убедиться, что индекс (в данном случае 1) меньше длины значений.
В целом, ваш код должен быть более структурированным и подготовленным для обработки условий ошибки (таких как отсутствие данных)
использование структурированной обработки исключений тоже может помочь. Поместите весь этот блок кода в блок try … catch.
Ответ №3:
Проблема, скорее всего, связана с возвратом, которого вы не ожидаете от своей базы данных. Где количество полей равно 0, и там для нет значений [1], и вы получаете исключение index
Ответ №4:
На основе вашего запроса:
//Getting the value from sql for totalUnits
sql = "SELECT count(distinct rp.repair_ord) " "FROM " schema ".repair_part rp "
"WHERE rp.repair_type = 'REFURB' and rp.ref_desig is null and rp.created_date > '" DateTime.Now.ToString("d-MMM-yyyy") "' ";
Вы должны использовать значения [0] вместо значений [1], поскольку этот запрос вернет только 1 столбец count(distinct rp.repair_ord)
. Либо это, либо запрос неверен, и вы хотите вернуть другие столбцы.
Комментарии:
1. Я в замешательстве, потому что мой первый запрос для totalRefurb устанавливает его массив в 0, чтобы получить информацию из базы данных. Так что, разве TotalUnits не должен быть равен 1, потому что вы не хотите, чтобы оба значения использовали один и тот же массив, верно; или я полностью неправ, и это не имеет значения?
2. @Justin, оба запроса возвращают 1 столбец, поэтому во втором запросе вы просто заменяете
values
переменную новым массивом, который снова содержит только один элемент, и поэтому он сноваvalues[0]
.3. @Justin Ты просто используешь одну и ту же
values
переменную и 2 отдельных массива. Обратите внимание, какvalues
назначаетсяvalues = new object[]
.
Ответ №5:
Вы захотите убедиться, что в массиве так много элементов…
if (values.Length >= 2) myvar = values[1];
это позволит вам увидеть, что массив содержит такое количество объектов, прежде чем использовать его.
и имейте в виду, что массивы начинают свой отсчет с объекта 0, поэтому к любому объекту, к которому вы хотите получить доступ, на единицу меньше длины. вам нужно.
it might be values.count im working from memory. let me know and i will ammend my post