Рейтинг:
9
OriginalGriff
Ты не можешь этого сделать.
У вас есть открытое соединение для обработки считывателя во внешнем пространстве while
цикл, и вы пытаетесь обновить ту же таблицу из того же соединения внутри этого цикла - эти операции несовместимы, поэтому вы получаете ошибку "база данных заблокирована".
Лучшим решением было бы сбросить считыватель и загрузить DataTable через DataAdapter, а затем использовать DataTable data для цикла и выполнения инструкций UPDATE.
"Ну, это не о том, что я сдаюсь, меня тошнит от этого обновления :)) Я пытался изменить код многими способами, но безуспешно. Это моя последняя попытка. Я получаю ту же ошибку. Я попытался закрыть и снова открыть соединение, чем закрыть снова, но безрезультатно. Я пробовал с DataAdapter, с DataReader, но это не сработало. Я не знаю, что еще можно попробовать. И я должен изменить только значение из одной строки, не понимаю, зачем использовать цикл foreach.."
Почему цикл foreach? Потому что запрос любой формы возвращает несколько строк - которые могут быть равны нулю (если нет совпадения), одному (если есть только одно) или нескольким (если есть более одного значения) - и это всегда хорошая практика, чтобы не предполагать, что он вернет один и только один, даже если логика вашей программы говорит, что это будет. Ошибки в данных случаются! :смеяться:
Так что начните с помощью объекта dataadapter, а не объект DataReader:
string collect = "SELECT option1,option2,option3 FROM questions WHERE question=@QU";
SQLiteCommand comp = new SQLiteCommand(collect, Conexiune.getConnection());
comp.CommandType = CommandType.Text;
comp.Parameters.AddWithValue("@QU", SimulatorManager.Intrebare);
SQLiteDataAdapter da = new SQLiteDataAdapter(comp);
DataTable dt = new DataTable();
da.Fill(dt);
foreach (DataRow row in dt.Rows)
{
...
}
(Я внес некоторые изменения в то, как вы это сделали: SQL-глаголы обычно пишутся в верхнем регистре, чтобы их было легче выбрать из SQL-оператора. И никогда, никогда не объединяйте строки для формирования SQL - оператора-этот способ приводит к атакам SQL-инъекций, которые могут повредить или уничтожить вашу базу данных, просто введя текстовые поля.
Всегда используйте параметризованные запросы!)
Затем в цикле вы просто используете информацию о строке, чтобы решить, нужно ли обновление:
int op1 = (int)row["option1"];
int op2 = (int)row["option2"];
int op3 = (int)row["option3"];
...
Есть ли смысл до сих пор?
DPaul1994
- Ты имеешь в виду вот так?
используя (обновление SQLiteDataAdapter = новый SQLiteDataAdapter("обновление totalsim от счета totalsim=totalsim+1 DPaul, где имя пользователя =''", Conexiune.метод getconnection()))
{
DataTable updt = новый DataTable();
обновление.Заполнить(интернета);
}
Потому что я попробовал это и получил:
Логическая ошибка SQL или отсутствующая база данных рядом с "from": синтаксическая ошибка
OriginalGriff
Вы проверили свой синтаксис SQL? :смеяться:
Обновите набор таблиц mytable ...
Нет
Обновить столбец mycolumn компонент компонент из таблицы mytable ...
DPaul1994
Омг! =)))) Да, извини за это. Но база данных по-прежнему заблокирована.
OriginalGriff
Это может быть глупый вопрос, но у вас все еще есть DataReader там? Покажите точный код, пожалуйста!
DPaul1994
Ну, это может быть глупый ответ, но это весь код :))) Я действительно не знаю, как использовать datatable..да :))
OriginalGriff
Нет, я подозреваю, что он все еще находится внутри цикла while, используя DataReader!
DPaul1994
Итак, используя SQLiteCommand, внутри этого - используя SQLiteDataReader - используя SQLiteDataAdapter и вот таблица?
OriginalGriff
Нет.
Используйте адаптер для заполнения таблицы из команды SELECT вместо DataReader, а затем используйте цикл foreach для доступа к строкам DataTable. Затем используйте команду SqLiteCommand внутри цикла для выполнения обновления.
Таким образом, при попытке выполнить обновление читатель не открывается, так как адаптер считывает и возвращает все строки сразу - читатель этого не делает, и именно поэтому SqLite жалуется.
DPaul1994
Хорошо, я попробую это сделать :)
DPaul1994
Мне не удалось его починить. Если вы можете написать код так, чтобы я мог точно видеть, о чем вы говорите, все в порядке, иначе это все. В любом случае спасибо за ваше время :)
OriginalGriff
Вы ничего не добьетесь, если будете все время сдаваться! :смеяться:
Давайте сделаем это в несколько простых этапов.
Какой код вы получили для своего выбора, используя DataAdapter?
DPaul1994
Ну, это не о том, что я сдаюсь, меня тошнит от этого обновления :)) Я пытался изменить код многими способами, но безуспешно. Это моя последняя попытка. Я получаю ту же ошибку. Я попытался закрыть и снова открыть соединение, чем закрыть снова, но безрезультатно. Я пробовал с DataAdapter, с DataReader, но это не сработало. Я не знаю, что еще можно попробовать. И я должен изменить только значение из одной строки, не понимаю, зачем использовать цикл foreach..
<pre lang="c#">
частный недействительными UpdateTotalSim()
{
используя (SQLiteCommand команду cmd = новый SQLiteCommand(@"приходится обновлять набор totalsim=totalsim+1 Где UserName='" + SimulatorManager.Утилизатор + "'", Conexiune.getConnection()))
{
пробовать
{
УМК.Метод executenonquery();
}
поймать (исключение бывший)
{
Ящик для сообщений.Показать(напр.сообщение);
}
}
}
частный недействительными button4_Click(объект отправителя, EventArgs в электронной)
{
если (check1.Проверено == true) result1 = 1;
еще результат1 = 0;
если (check2.Проверено == true) result2 = 1;
еще результат2 = 0;
если (check3.Проверено == true) result3 = 1;
еще result3 = 0;
строка collect = "Select option1,option2,option3 from questions where `question`='" + SimulatorManager.Intrebare + "'";
SQLiteCommand комп = новый SQLiteCommand(сбор, Conexiune.метод getconnection());
компания.Свойство Commandtype = Значение Commandtype.Текст;
SQLiteDataReader read = comp.ExecuteReader(CommandBehavior.Значение closeconnection);
пробовать
{
в то время как (читай.Прочитай())
{
int op1 = (int)читать["option1"];
int op2 = (int)читать["option2"];
int op3 = (int)читать["option3"];
если (check1.Checked == false && check2.Checked == false && check3.Проверено == ложь)
Ящик для сообщений.Шоу("Selectati minim o optiune");
еще
{
если ((результат1 == ОР1) и усилитель; & (результат2 == ампер еп2) &;&ампер; (result3 == op3 отображается))
{
правильно++;
label4.Текст = правильно.Метод toString();
проверка 1.Проверено = ложь;
проверка2.Проверено = ложь;
чек-3.Проверено = ложь;
выбирать();
}
еще
{
некорректное++;
label6.Текст = неверный.Метод toString();
проверка 1.Проверено = ложь;
проверка2.Проверено = ложь;
чек-3.Проверено = ложь;
выбирать();
}
если (corect + incorect == 1)
{
Ящик для сообщений.Шоу("тестовый терминал!");
если (corect == 1)
{
UpdateTotalSim(); // здесь я вызываю функцию обновления
Ящик для сообщений.Шоу("Браво!");
}
еще
{
Ящик для сообщений.Шоу("Bleah");
}
этот.Закрывать();
}
}
}
}
поймать (исключение бывший)
{
Ящик для сообщений.Показать(напр.сообщение);
}
}
</pre>
DPaul1994
Я не знаю, имеет ли это значение, но у меня есть еще одна функция, которая выбирает некоторые данные и вызывается в форме загрузки. (использование SQLiteDataReader)
OriginalGriff
Ответ обновлен.
И это может быть - вы закрываете считыватель, команду и соединение, когда вы закончите с ними?
DPaul1994
То, что вы сделали, - это просто пример того, как я могу это сделать, верно? Причина-это не то, что я должен делать. Сначала я должен собрать и сравнить, затем я должен обновить, вы это понимаете, верно? Нет, я их не закрываю ... связь всегда открыта. Я попробую сделать это сейчас
OriginalGriff
"Я должен собрать и сравнить, а затем я должен обновить"
Вот что это делает: адаптер данных считывает всю информацию из БД, а затем возвращает ее как DataTable - DateReader этого не делает: он считывает строку за раз каждый раз, когда вы вызываете метод Read, и база данных "занята" до тех пор, пока читатель и связанная с ним команда не будут закрыты. Вот почему вы получаете ошибку при попытке обновления в вашем цикле - таблица заблокирована кодом цикла.
Использование адаптера данных позволяет считывать все данные, а затем обрабатывать их позже, после завершения команды и разблокировки таблицы.
Дайте ему попробовать!
DPaul1994
Omg Smile | :) ) это сработало. Я постараюсь изучить и понять этот способ обновления с помощью DataTable. Спасибо Вам за ваше терпение и желаю всего наилучшего!
OriginalGriff
Всегда пожалуйста!