Russian Qt Forum
Апрель 27, 2024, 01:35 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: База данных (QSqlDatabase) по умолчанию?  (Прочитано 13998 раз)
PinkPanther
Самовар
**
Offline Offline

Сообщений: 169



Просмотр профиля
« : Февраль 21, 2015, 16:52 »

В классе MainWindow я дописал переменную базы QSqlDatabase db, в конструкторе база определяется и открывается. Там же определяется QSqlQuery query(db).
В других классах иногда требуется обращаться к этой базе. Нужно ли при объявлении новых объектов QSqlQuery задавать базу явным образом, или все они будут обращаться к единственной открытой?
Записан

Эвтаназия - наше хобби!
Johnik
Крякер
****
Offline Offline

Сообщений: 339


Просмотр профиля
« Ответ #1 : Февраль 21, 2015, 22:35 »


В классе MainWindow я дописал переменную базы QSqlDatabase db, в конструкторе база определяется и открывается.
В классе MainWindow, лучше вообще не хранить QSqlDatabase, инициализировать, но не хранить.
Нужно ли при объявлении новых объектов QSqlQuery задавать базу явным образом, или все они будут обращаться к единственной открытой?
Если имя при инициализации не задавали, то будет использоваться подключение по умолчанию, и не будет надобности каждый раз указывать QSqlDatabase.
Записан
PinkPanther
Самовар
**
Offline Offline

Сообщений: 169



Просмотр профиля
« Ответ #2 : Февраль 26, 2015, 05:51 »

Цитировать
В классе MainWindow, лучше вообще не хранить QSqlDatabase[/qupte]
Согласен...

Цитировать
Если имя при инициализации не задавали, то будет использоваться подключение по умолчанию
У меня это почему-то не работает. Попытка создать еще одну переменную QSqlQuery без задания имени базы приводит к ошибке исполнения запроса этой переменной...
Вероятно, я не определил коннекшн по умолчанию. С этим разберусь, спасибо.

Господа, еще один вопрос:

Можно ли использовать одну и ту же базу разными приложениями параллельно? Приложения находиться в одной папке, база находится там же. У меня как только одно приложение открывает базу, остальные работать с ней не могут.
Записан

Эвтаназия - наше хобби!
Termit
Самовар
**
Offline Offline

Сообщений: 144



Просмотр профиля WWW
« Ответ #3 : Февраль 26, 2015, 09:00 »

Да, можно. Даже такие базы как sqlite - указывается таймаут ожидания базы и все работает. А для обычных СУБД так вообще не вопрос.
Записан

Человеческая глупость дает представление о бесконечности
(с) Иоанна Хмелевская
PinkPanther
Самовар
**
Offline Offline

Сообщений: 169



Просмотр профиля
« Ответ #4 : Февраль 26, 2015, 21:25 »

Да, можно. Даже такие базы как sqlite - указывается таймаут ожидания базы и все работает. А для обычных СУБД так вообще не вопрос.

Спасибо! Если я правильно понял, вы предлагаете открывать базу по требованию, и закрывать в конце работы, отдавая файл другим приложениям. При этом, если база занята, ждать и разумное время крутить цикл событий. Правильно?

А можно ли сделать иначе - открыть базу (файл) для нескольких приложений одновременно? В моем случае есть важная особенность - приложения читают общую информацию, а пишут только в свои личные строки/таблицы. Коллизий возникнуть не может.
Можно ли организовать несколько подключений к одной и той же базе из разных процессов, или вариант доступа с ожиданием самый оптимальный?
Записан

Эвтаназия - наше хобби!
Termit
Самовар
**
Offline Offline

Сообщений: 144



Просмотр профиля WWW
« Ответ #5 : Февраль 27, 2015, 09:02 »

Первое предположение неверное. Я писал именно про второй вариант.
Давайте немного конкретизируем: о какой СУБД мы говорим?
Записан

Человеческая глупость дает представление о бесконечности
(с) Иоанна Хмелевская
PinkPanther
Самовар
**
Offline Offline

Сообщений: 169



Просмотр профиля
« Ответ #6 : Февраль 28, 2015, 12:18 »

Первое предположение неверное. Я писал именно про второй вариант.
Давайте немного конкретизируем: о какой СУБД мы говорим?

SQLite 3, стандартная поставка Qt, создается/открывается в 5 строчек кода, создается объект QSqlDatabase, у меня он называется db. Все, что касается открытия, скопировано из хелпов и книги Шлее. После открытия можно создать неограниченное количество QSqlQuery(db), и все они будут иметь доступ к базе.
У меня имеется несколько приложений, которые хотели бы иметь доступ к одной базе, но когда база открыта одним приложением, остальные приложения получить к ней доступ не могут.
Записан

Эвтаназия - наше хобби!
Termit
Самовар
**
Offline Offline

Сообщений: 144



Просмотр профиля WWW
« Ответ #7 : Февраль 28, 2015, 12:28 »

Делайте где-то так
Код
C++ (Qt)
   database = QSqlDatabase::addDatabase("QSQLITE");
   database.setConnectOptions("QSQLITE_BUSY_TIMEOUT=5000");
 
Время ожидания освобождения базы - 5 сек. Можно поставить любое.
У меня несколько приложений (в основной массе 2 одновременно, не считая потоков) замечательно работают с одной базой, за 5-6 лет не было еще ни одного случая когда они базу не поделили. И кол-во машин на которых это работает 1000+.
Единственное на операциях которые длятся заведомо дольше чем 5 секунд (массовая заливка данных в базу) я отслеживаю время выполнения запросов и делаю транзакции не более 3-х секунд.
Записан

Человеческая глупость дает представление о бесконечности
(с) Иоанна Хмелевская
Termit
Самовар
**
Offline Offline

Сообщений: 144



Просмотр профиля WWW
« Ответ #8 : Февраль 28, 2015, 12:31 »

И еще:
При работе с QSqlQueryModel нужно обязательно использовать canFetchMore.
Записан

Человеческая глупость дает представление о бесконечности
(с) Иоанна Хмелевская
PinkPanther
Самовар
**
Offline Offline

Сообщений: 169



Просмотр профиля
« Ответ #9 : Февраль 28, 2015, 17:02 »

Делайте где-то так
Код
C++ (Qt)
   database = QSqlDatabase::addDatabase("QSQLITE");
   database.setConnectOptions("QSQLITE_BUSY_TIMEOUT=5000");
 
Время ожидания освобождения базы - 5 сек. Можно поставить любое.
У меня несколько приложений (в основной массе 2 одновременно, не считая потоков) замечательно работают с одной базой, за 5-6 лет не было еще ни одного случая когда они базу не поделили. И кол-во машин на которых это работает 1000+.
Единственное на операциях которые длятся заведомо дольше чем 5 секунд (массовая заливка данных в базу) я отслеживаю время выполнения запросов и делаю транзакции не более 3-х секунд.

Спасибо! И если установить этот параметр, ошибки на стадии открытия - лока базы, если она уже открыта одним приложением - возникать не будет? У меня проблема именно в этом. Если база уже открыта, никаких проблем записи-считывания не возникает.

Я хотел решить проблему немного иначе - установить таймаут непосредственно на стадии чтения-записи, встроив его в производный от QSqlQuery класс. Столкнувшись с ошибкой открытия, пришел к мысли, что, если не получается открыть базу одновременно, ее можно открывать по необходимости, а таймаут встроить в метод открытия базы. Открываем, если база залочена - ждем те же 5 секунд (в моем случае, т.к. запросы простые и редкие, должно хватить 2-3 секунд), быстро делаем необходимое и закрываем, освобождая файл базы для других процессов.
К тому же, это сразу избавит от возможных коллизий, когда одно приложение частично изменило таблицу, а второе в этот же момент хочет получить оттуда данные.
Записан

Эвтаназия - наше хобби!
Termit
Самовар
**
Offline Offline

Сообщений: 144



Просмотр профиля WWW
« Ответ #10 : Февраль 28, 2015, 17:11 »

Спасибо! И если установить этот параметр, ошибки на стадии открытия - лока базы, если она уже открыта одним приложением - возникать не будет? У меня проблема именно в этом. Если база уже открыта, никаких проблем записи-считывания не возникает.

Кстати про лок. Я работаю под Linux-ом. Может как-то зависит?

Ну, а в целом не должно быть локов. Eсли каждое из приложений будет укладываться со своими запросами в 5 секунд и при работе с моделями из запросов будут выгребаться записи через canFetchMore.
Попутно порекомендовал бы для записи использовать транзакции, а для чтения если перебор идет только в одном направлении для запроса указывать setForwardOnly(true).
Записан

Человеческая глупость дает представление о бесконечности
(с) Иоанна Хмелевская
PinkPanther
Самовар
**
Offline Offline

Сообщений: 169



Просмотр профиля
« Ответ #11 : Февраль 28, 2015, 19:22 »

Спасибо! И если установить этот параметр, ошибки на стадии открытия - лока базы, если она уже открыта одним приложением - возникать не будет? У меня проблема именно в этом. Если база уже открыта, никаких проблем записи-считывания не возникает.

Кстати про лок. Я работаю под Linux-ом. Может как-то зависит?

Ну, а в целом не должно быть локов. Eсли каждое из приложений будет укладываться со своими запросами в 5 секунд и при работе с моделями из запросов будут выгребаться записи через canFetchMore.
Попутно порекомендовал бы для записи использовать транзакции, а для чтения если перебор идет только в одном направлении для запроса указывать setForwardOnly(true).

У меня все под Windows.
Лок, вероятно, связан с открытием файла... Приложение открывает базу как обычный файл, на чтение и запись, и другие приложения не могут получить доступ. Другие причины в голову не приходят. Фактически, я и хочу работать в режиме транзакций, т.к. использование базы будет ограничено одним потоком (работа с Model не реализована, только ручные SQL-запросы). Пока работа порции кода не закончена, другие приложения к базе доступ не получают, хотя бы из-за лока. А чтобы избежать коллизий внутри приложения, можно проверять, открыта ли база. Если открыта, ждем, пока закроют, если закрыта - открываем.
Записан

Эвтаназия - наше хобби!
Termit
Самовар
**
Offline Offline

Сообщений: 144



Просмотр профиля WWW
« Ответ #12 : Февраль 28, 2015, 19:42 »

Неужели и правда под Windows такое не работает? Вот блин!
А покажите код которым подключаете базу.
Записан

Человеческая глупость дает представление о бесконечности
(с) Иоанна Хмелевская
PinkPanther
Самовар
**
Offline Offline

Сообщений: 169



Просмотр профиля
« Ответ #13 : Февраль 28, 2015, 20:35 »

Неужели и правда под Windows такое не работает? Вот блин!
А покажите код которым подключаете базу.

Код взят то ли из книжки, или из мануала. Ему года 4, с тех пор ничего менять не требовалось.

Код:
db = QSqlDatabase::addDatabase("QSQLITE");
db.setHostName("myhostname.ru");
db.setDatabaseName("PinkPanther");
db.setUserName("PinkPanther");
db.setPassword("123XYZ321");
if(!db.open())
{
    showCritical("Can't open DATABASE!");
    exit(1);
}
query = QSqlQuery(db);

QSqlDatabase db и QSqlQuery query объявлены в классе главного окна, а код запускается в конструкторе главного окна. В деструкторе база закрывается.
Записан

Эвтаназия - наше хобби!
Termit
Самовар
**
Offline Offline

Сообщений: 144



Просмотр профиля WWW
« Ответ #14 : Февраль 28, 2015, 20:55 »

Подозреваю, что это из-за того как Windows работает с файлами.
Такой подход как я описал, видимо, возможен только или из одного приложения в несколько потоков, или из разных приложений но только под *nix системами.
Записан

Человеческая глупость дает представление о бесконечности
(с) Иоанна Хмелевская
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.101 секунд. Запросов: 22.