Patrick Skelton Ответов: 2

Как использовать функцию sqlite max () из C#?


Я использую базу данных SQLite из приложения C#/WPF. У меня есть таблица, в которой есть столбец, объявленный как ЦЕЛОЕ ЧИСЛО УНИКАЛЬНО.

Я выполняю приведенный ниже SQL-скрипт из своего обычного ExecuteReader() код и я получаем один единственный результат, которого я и ожидал. Проблема в том, что результат всегда равен нулю. Кто-нибудь знает, что я может быть делаю не так?

SELECT max( enquiry_job_number ) FROM EnquiryJobs;


Что я уже пробовал:

Глядя в отладчик, оказывается, что столбец не существует. Даже если я добавлю АС предложение к SQL (показано ниже), именованному столбцу SQLiteDataReader.GetOrdinal( columnName ) возвращает -1.

SELECT max( enquiry_job_number ) FROM EnquiryJobs AS "ABC";

ZurdoDev

ExecuteScalar (), скорее всего, будет лучшим вариантом. Он возвращает первый столбец первой строки. В противном случае опубликуйте код для ExecuteReader и код вокруг него, чтобы увидеть, что вы, возможно, делаете неправильно.

Patrick Skelton

Выдающийся! Это прекрасно работает. Это могло бы прийти мне в голову еще до Рождества, если бы мне повезло. Спасибо.

2 Ответов

Рейтинг:
5

ZurdoDev

Как уже упоминалось в комментариях, вместо этого используйте ExecuteScalar, так как он возвращает первый столбец первой строки.

А чтобы использовать DataReader, см. Решение 1.


OriginalGriff

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

Patrick Skelton

Одна из проблем, с которой я сталкиваюсь с ExecuteScalar (), заключается в том, что при первом запуске на пустой базе данных я не получаю null. Я получаю объект, который просто показывает пустой набор скобок в отладчике. Я не уверен, что это такое или, что более важно, что если () оператор я могу написать, чтобы поймать этот первый запуск.

ZurdoDev

Объект temp = cmd.Executescalar так();
if (temp != null){
Строка jobNo = temp.Метод toString();
}

Patrick Skelton

Боюсь, что это не сработает. Я тестирую против null, получаю false, но затем получаю исключение, когда пытаюсь привести результат к int. Нужно ли мне тестировать DbNull или что-то в этом роде? (Как вы, без сомнения, поняли, я не эксперт по SQL.)

ZurdoDev

Что является результатом темп.Метод toString()?

Patrick Skelton

Используя следующий код:

if (result != null )
{
строка s = (строка)результат;
int x = 10;
}

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

Patrick Skelton

Ах ... следующие работы:

if (result != DBNull.Ценность )
{
...
}
Спасибо за вашу помощь.

ZurdoDev

То, что я выложил, должно было сработать. Наверное,мне нужно было бы увидеть код, который присваивает результат.

Но рад, что это работает.

Patrick Skelton

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

SQLiteDataStore.Соединение.Открыть();
string sqlScript = " SELECT max (enquiry_job_number ) FROM EnquiryJobs;";
SQLiteCommand sqlCommand = new SQLiteCommand( sqlScript, SQLiteDataStore.Соединение );
результат объекта = sqlCommand.Executescalar так();
если( результат != нуль &амп;&амп; результат != Значение dbnull.Ценность )
{
// По крайней мере одна запись в БД.
}
ещё
{
// Нет записей в БД.
}

ZurdoDev

Хмм. Должно быть, это как-то связано с SqlLite, потому что я проверяю только null, и это всегда работает. Если что-то действительно вернется как DBNull.Стоимость вызова toString() дает пустую строку.

Во всяком случае, это работает, и это самое главное.

Patrick Skelton

К сожалению, я заговорил слишком рано. Теперь у меня есть подход ремня и подтяжек, показанный ниже. Когда управление проходит мимо моего оператора over-the-top if (), отладчик показывает допустимое положительное целое число; однако, когда я выполняю приведение, я получаю недопустимое исключение приведения. У кого-нибудь есть какие-нибудь идеи, что может произойти? Думаю, что, возможно, придется попробовать метод executenonquery и вместо заявленного подхода колонны. Я просто не появляются, чтобы быть в состоянии сделать что-нибудь надежное с результатом executescalar так.

SQLiteDataStore.Соединение.Открыть();
string sqlScript = " SELECT max (enquiry_job_number ) FROM EnquiryJobs;";
SQLiteCommand sqlCommand = new SQLiteCommand( sqlScript, SQLiteDataStore.Соединение );
результат объекта = sqlCommand.Executescalar так();
если( результат != нуль &амп;&амп; результат.ToString() != Строка.Пустой& & amp; результат != DBNull.Ценность )
{
// По крайней мере одна запись в БД; отладчик показывает положительный int, но следующее приведение дает исключение. :(
int resultAsInteger = (int)результат;
}
ещё
{
// Нет записей в БД.
}

ZurdoDev

Какое значение показывает результат в окне просмотра?

Patrick Skelton

Он показывает действительное положительное целое число.

ZurdoDev

Что именно?

Patrick Skelton

Он показывает (с каждой строкой, вложенной в ту, что выше):
результат {} объект {система.Значение dbnull}
Статический член
Ценность {} Система.Значение dbnull

На самом деле, теперь, когда вы заставили меня написать его, я вдруг понял, как, черт возьми, он проходит мимо моего оператора if (), если значение равно DBNull? Это означает, что у меня есть два разных значения для DBNull. Можно ли тестировать DBNull со стандартным оператором'=='?

Patrick Skelton

О, подожди. Я перепутал два варианта использования. Когда возвращаемое значение является допустимым числом, его тип - "long", что объясняет недопустимое приведение. Дох! Моя глупая ошибка. Спасибо,что позволил мне отскочить от тебя. В противном случае я потратил бы гораздо больше времени, добираясь до результата.

ZurdoDev

Рад это слышать.

Рейтинг:
14

OriginalGriff

В дополнение к превосходному предложению Ряндева, стоит также отметить, что если вы используете этот SQL:

SELECT max( enquiry_job_number ) FROM EnquiryJobs;
Вы не можете получить доступ к данным из DataReader, как это:
SQLiteDataReader.GetOrdinal( columnName )
Потому что вы вообще не дали столбцу данных имени.
В будущем попробуйте назвать столбец, когда вы его вернете:
SELECT max( enquiry_job_number ) AS MaxJobNo FROM EnquiryJobs;
И вы можете получить доступ к столбцу по имени:
int max = (int) myDataReader["MaxJobNo"];


Patrick Skelton

Спасибо тебе за это. Обычно я называю возвращаемые значения. Я ошибочно предположил, что имя будет таким же, как и имя столбца.

OriginalGriff

Не тогда, когда вы применяете агрегатную функцию!