Russian Qt Forum

Qt => Базы данных => Тема начата: Garfild от Март 18, 2010, 15:47



Название: Два соединения к базе данных
Отправлено: Garfild от Март 18, 2010, 15:47
Есть два соединения с базой данных. Одно соединение отображает таблицу БД(1-е соединение), а другое соединение(2-е соединение) копирует одну из строчек таблицы... После копирования, хочу чтобы таблица обновлялась... но вот иногда когда я обращаюсь к 1-му подключению,данные в таблице отображаются старые..т.е. без изменений,которые были сделаны 2-м подключением ... как же можно обновить это 1-е подключение??


Название: Re: Два соединения к базе данных
Отправлено: cya-st от Март 18, 2010, 16:19
Сделай в проге одно соединение.


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 18, 2010, 16:22
Просто если одно соединение сделать, то когда это содинение отражает таблицу, я не могу транзакцию использовать... поэтому и пришлось два соединения использовать


Название: Re: Два соединения к базе данных
Отправлено: lit-uriy от Март 18, 2010, 16:46
данные в представлении обновляются при изменении модели. Попробуй по завершению копирования делать для неё select()


Название: Re: Два соединения к базе данных
Отправлено: dio от Март 18, 2010, 16:51
Делаете ли вы commit во 2-м соединении?
Ну и хорошо бы рассказать: какую БД используете, как устанавливаете соединение, как делаете запрос данных, как модифицируете данные.


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 18, 2010, 17:01
В том-то и дело... я после завершения копирования для модели делаю setQuery()...и вот что заметил, после того как первый раз скопирую данные не обновляються даже после вызова setQuery()... а потом все нормально... только после второго вызова появляется сразу две новых строчки(т.е. еще та строчка,которая не появилась после первого вызова), а потом все как-надо. Хотя первый раз setQuery вызывается -  проверено


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 18, 2010, 17:03
В том-то и дело... я после завершения копирования для модели делаю setQuery()...и вот что заметил, после того как первый раз скопирую данные не обновляються даже после вызова setQuery()... а потом все нормально... только после второго вызова появляется сразу две новых строчки(т.е. еще та строчка,которая не появилась после первого вызова), а потом все как-надо. Хотя первый раз setQuery вызывается -  проверено

щас тока домой приду и расскажу  :)


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 18, 2010, 18:16
Использую Access.
При вызове программка сразу же подклюсается к БД
Код
C++ (Qt)
bool MainWindow::createConnection()
{
   QDir dir("data");
   QString fileName = dir.absolutePath().replace("/","\\") + "\\accounts.mdb";
   db = QSqlDatabase::addDatabase("QODBC");
   db.setDatabaseName("DRIVER={Microsoft Access Driver (*.mdb)};FIL={MS Access};DBQ=" + fileName);
   if(!db.open())
   {
       QMessageBox::critical(this,tr("Ошибка"),db.lastError().text());
       return false;
   }
   return true;
}
 
при копировании делаю так
Код
C++ (Qt)
bool copy(int rf_IDSmetiCopy){
QSqlDatabase db = QSqlDatabase::database();
   {
     QSqlDatabase dbase = QSqlDatabase::cloneDatabase(db,"other");
     if(!dbase.open())
     {
         QMessageBox::critical(this,tr("Ошибка"),dbase.lastError().text());
         return false;
     }
 
     dbase.transaction();
 
     QSqlQuery query(dbase);
 
     if(!query.exec(tr("INSERT ..."))
     {
         QMessageBox::critical(this,tr("Ошибка SQL"),query.lastError().text());
         dbase.rollback();
         return false;
     }
 
     query.clear();
     query.exec("INSERT");
     if(query.lastError().isValid()){
         QMessageBox::critical(this,tr("Ошибка SQL"),query.lastError().text());
         dbase.rollback();
         return false;
     }
     emit copyEndTabl();
 
   //i t.d.
 
     dbase.commit();
     dbase.close();
   }
   QSqlDatabase::removeDatabase("other");
   return true;
}
 
ну и обновляю данные потом с помощью setQuery()


Название: Re: Два соединения к базе данных
Отправлено: cya-st от Март 18, 2010, 18:39
Цитировать
()...и вот что заметил, после того как первый раз скопирую данные не обновляються даже после вызова setQuery()... а потом все нормально... только после второго вызова появляется сразу две новых строчки(т.е. еще та строчка,которая не появилась после первого вызова)
в таблице не обновляется?


Название: Re: Два соединения к базе данных
Отправлено: cya-st от Март 18, 2010, 20:25
или вывод в QTableView или куда нибудь еще?


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 18, 2010, 20:48
Цитировать
()...и вот что заметил, после того как первый раз скопирую данные не обновляються даже после вызова setQuery()... а потом все нормально... только после второго вызова появляется сразу две новых строчки(т.е. еще та строчка,которая не появилась после первого вызова)
в таблице не обновляется?

Просто при вызове model->setQuery() основного соединения, почему-то не всегда отображается данные вставленные с помощью 2-го соединения...то отображаются,а то нет... не пойму от чего это зависит


Название: Re: Два соединения к базе данных
Отправлено: dio от Март 19, 2010, 09:48
Вы обновляете данные при обработке сигнала copyEndTabl или после выполнения метода copy?


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 19, 2010, 10:14
обновляю данные после метода copy.. т.е. к тому моменту второе соединение у меня уже закрыто. И такое ощущение, что в первои соединении еще не отразились изменения, которые произошли во втором.
...то отображаются,а то нет... не пойму от чего это зависит


Название: Re: Два соединения к базе данных
Отправлено: dio от Март 19, 2010, 11:11
Если есть возможность, погоняйте свой код с другой многопользовательской БД. Вполне возможно, что дело в Access'e.


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 22, 2010, 09:06
Если перед обновлением таблицы,т.е. методом setQuery() повторно открыть БД (1-е соединение), т.е. сделать
Код
C++ (Qt)
QSqlDatabase db = QSqlDatabase::database();
db.open();
 
то все нормально обновляется. Только насколько это корректно??? Получается мы БД открываем два раза


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 22, 2010, 16:28
Скажите пожалуйста, если я повторно открою базу это же ни к каким последствиям не приведет???


Название: Re: Два соединения к базе данных
Отправлено: dio от Март 22, 2010, 17:01
Ну если только на производительности скажется при частом выполнении. Если у вас многопользовательское приложение, я все же советую разобраться почему не видны изменения, выполненные в другой сессии.


Название: Re: Два соединения к базе данных
Отправлено: MoPDoBoPoT от Март 22, 2010, 18:23
Ты, случаем, в первом соединении явно транзакцию не начинаешь?

Просто если одно соединение сделать, то когда это содинение отражает таблицу, я не могу транзакцию использовать... поэтому и пришлось два соединения использовать
Обоснуй (:


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 22, 2010, 22:37
Ты, случаем, в первом соединении явно транзакцию не начинаешь?

Просто если одно соединение сделать, то когда это содинение отражает таблицу, я не могу транзакцию использовать... поэтому и пришлось два соединения использовать
Обоснуй (:

У меня в tableView отображается таблица из БД, и когда я пытаюсь использовать транзакцию, почему-то вылетает предупреждение

[Microsoft][Драйвер ODBC Microsoft Access]Задать атрибут сейчас нельзя  QODBC3: Unable to disable autocommit


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 22, 2010, 22:44
А вообще,вот пытаюсь использовать два соединения без транзакции....одно соединение отображает таблицу, а другое вставляет строчку в таблицу - та же фигня. Почему-то при первом добавлении,изменения не отображаются, а при последующий добавлениях все добавленные строчки(включая и первую добавленную) отображаются.. Может я чего-то не вижу...
Вот код:
Код
C++ (Qt)
MainWindow::MainWindow(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::MainWindow)
{
   ui->setupUi(this);
   createConnection();
   m=new QSqlQueryModel();
   ui->tableView->setModel(m);
   refresh();
   connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(slotAdd()));
   connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(slotRefr()));
}
 
MainWindow::~MainWindow()
{
   delete ui;
}
bool MainWindow::createConnection()
{
   QDir dir("data");
   QString fileName = dir.absolutePath().replace("/","\\") + "\\accounts.mdb";
   db = QSqlDatabase::addDatabase("QODBC");
   db.setDatabaseName("DRIVER={Microsoft Access Driver (*.mdb)};FIL={MS Access};DBQ=" + fileName);
   if(!db.open())
   {
       QMessageBox::critical(this,tr("Ошибка"),tr(db.lastError().text());
       return false;
   }
   return true;
}
void MainWindow::slotRefr(){
   refresh();
}
void MainWindow::refresh(){
   QSqlDatabase db = QSqlDatabase::database();
   m->setQuery("Select * from [Account]",db);
   ui->tableView->setCurrentIndex(m->index(0,0));
}
 
bool MainWindow::add(){
   QSqlDatabase db = QSqlDatabase::database();
   {
      QSqlDatabase dbase = QSqlDatabase::cloneDatabase(db,"other");
      if(!dbase.open())
      {
         QMessageBox::critical(this,tr("Ошибка"),tr(dbase.lastError().text());
         return false;
      }
      QSqlQuery q=QSqlQuery(dbase);
      q.exec("INSERT INTO [Account](Num,Dat,Year) "
             "                  Values( 123455, "
             "                          1, "
             "                          #22/03/2010#, "
             "                          2010 )");
      if(q.lastError().isValid()){
          QMessageBox::information(this,"",q.lastError().text());
          return false;
      }
      dbase.close();
  }
   QSqlDatabase::removeDatabase("other");
   return true;
}
void MainWindow::slotAdd(){
   if(add()){
     refresh();
     QMessageBox::information(this,"","Добавилось");
   }
}
 


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 23, 2010, 10:23
Кажется все дело в использовании cloneDatabase() для определения второго соединения
Вот нашел в Ассистенте:
Цитировать
Любые изменения, сделаные в соединении с базой данных через один объект QSqlDatabase, будут влиять на другие объекты QSqlDatabase, представляющие это же соединение. Вызовите cloneDatabase(), если вы хотите создать независимое соединение с базой данных на основе существующего.

Значит лучше сделать так
QSqlDatabase dbase = QSqlDatabase::addDatabase("QODBC","other");
dbase = QSqlDatabase(db);

Правда при закрытии dbase,основное соединение db тоже закрывается


Название: Re: Два соединения к базе данных
Отправлено: Garfild от Март 23, 2010, 11:00
А если использую
Код
C++ (Qt)
QSqlDatabase dbase = QSqlDatabase(db);
 
то транзакцию не получается использовать - вываливается предупреждение
Цитировать
[Microsoft][Драйвер ODBC Microsoft Access]Задать атрибут сейчас нельзя  QODBC3: Unable to disable autocommit