Параметр, возвращаемый не в правильном формате

#c# #sql #async-await

Вопрос:

У меня есть асинхронный метод задачи, который запрашивает в таблице базы данных общее количество кредитов в определенном столбце. У меня есть строковый параметр в методе, который я использую для запроса, чтобы определить, какой пользователь вошел в систему, в котором он хранится Properties.Settings.Default.Student_Number; . Столбец для номера студента в базе данных-это переменный символ, а везде в моем коде-строка, но я получаю сообщение об исключении Input string was not in correct format . Есть идеи, что я делаю не так

 private async Tasklt;intgt; Count_Credits(string student_number) {  int count = 0;  string sql = "SELECT SUM(Module_Credit) AS TOTAL_CREDITS FROM Module_Data WHERE Student_Number=@num";   using (var conn = new SqlConnection(connString))  using (var cmd = new SqlCommand(sql, conn))  {   cmd.Parameters.Add("@num", SqlDbType.VarChar, 55).Value = student_number;  await conn.OpenAsync();   count = int.Parse(cmd.ExecuteScalar().ToString());  }   return count; }  

Как я вызываю метод

 Tasklt;intgt; count_credits = Count_Credits(Student_Number); module_info.Total_Credits = await count_credits; //Exception Goes to this line  

Я использую привязку на этикетке для

 module_info.Total_Credits  

Комментарии:

1. Какое исходное значение возвращается cmd.ExecuteScalar() ?

2. У меня пока нет никаких значений в базе данных, но я бы даже не знал, что такое возврат, поскольку я получаю исключение до того, как что-либо сможет вернуться

3. Я хочу, чтобы он был возвращен равным 0, если в таблице нет данных

4. если ничего больше не работает, выясните, в какой именно строке в Count_Credits возникает исключение. Это анализ int.или связано с SQL-запросом?

5. Исключение относится к методу с параметром, ни одно исключение не относится к sql или синтаксическому анализу

Ответ №1:

Вам нужно будет проверить, возвращен ли результат ExecuteScalar , прежде чем вы сможете привести тип.

 object result = cmd.ExecuteScalar(); if(result != null) {  count = (int)result; }  

Для более краткой проверки используйте сопоставление с образцом (согласно комментарию Оливье).:

 if(cmd.ExecuteScalar() is int i)  {   count = i;  }  

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

 int count_credits = await Count_Credits(Student_Number); module_info.Total_Credits = count_credits;  

Комментарии:

1. Имеет ли значение, куда я поместил ожидание

2. TBH это должно быть исправлено в самом запросе. Пользователь упомянул: What I want to have it returned is 0 if no data is in the table что можно легко сделать, изменив запрос.

3. или с сопоставлением шаблонов if(cmd.ExecuteScalar() is int i) { count = i; }

4. @OlivierJacot-Дескомб — согласен. Просто не хотел вдаваться во что-то более продвинутое.

5. @OlivierJacot-Дескомб Можете ли вы оставить свой комментарий в качестве ответа, пожалуйста

Ответ №2:

Результат, возвращаемый пользователем ExecuteScalar , будет либо an int , либо be null . Кроме того, нет необходимости совершать поездку туда и обратно по строке. Но мы должны проверить null .

Сопоставление шаблонов было введено в последних версиях C#, что позволяет использовать код terser во многих ситуациях:

 count = cmd.ExecuteScalar() is int i ? i : 0;  

Если скаляр представляет собой упакованный int объект, он будет приведен к int новой переменной и назначен i ей, и результатом is выражения будет true . Мы используем этот результат в троичном выражении для определения конечного результата.


Еще одна возможность:

 count = (cmd.ExecuteScalar() as int?) ?? 0;  

Оператор as приводит входные данные к нужному типу, если приведение выполнено успешно, и в противном случае возвращает null . Поэтому целевой тип должен быть обнуляемым. Следовательно, мы указываем int? (= Nullablelt;intgt; ) в качестве целевого типа. Мы используем оператор объединения null ?? для преобразования null в 0 .