#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
.