Customize Consent Preferences

We use cookies to help you navigate efficiently and perform certain functions. You will find detailed information about all cookies under each consent category below.

The cookies that are categorized as "Necessary" are stored on your browser as they are essential for enabling the basic functionalities of the site. ... 

Always Active

Necessary cookies are required to enable the basic features of this site, such as providing secure log-in or adjusting your consent preferences. These cookies do not store any personally identifiable data.

No cookies to display.

Functional cookies help perform certain functionalities like sharing the content of the website on social media platforms, collecting feedback, and other third-party features.

No cookies to display.

Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics such as the number of visitors, bounce rate, traffic source, etc.

No cookies to display.

Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.

No cookies to display.

Advertisement cookies are used to provide visitors with customized advertisements based on the pages you visited previously and to analyze the effectiveness of the ad campaigns.

No cookies to display.

Skip to content Skip to footer

Работа с базами данных в wxWidgets – DatabaseLayer – Минимальное приложение

Вслед за анонсом новой версии DatabaseLayer, кросс-платформенной библиотеки для работы с базами данных, решил выложить небольшой туториал с примером использования DatabaseLayer.

В этот раз мы рассмотрим пример создания простейшего консольного приложения, использующего эту библиотеку для работы с базами данных.

В качестве среды разработки будем использовать Visual Studio. Это самый простой способ добиться желаемого результата. Бесплатная версия Visual Studio Express Edition тоже вполне подойдет для создания приложений на С++/wxWidgets.

Для начала создадим консольное приложение и назовем его DatabaseLayerMinimal.

databaselayerminimal_01

В настройках проекта указываем тип приложение Console Application и стамим маркер на Empty Project.

databaselayerminimal_02

После того как мы создали проект, распаковываем DatabaseLayer рядом с папкой, в которой находится .sln-файл решения.

databaselayerminimal_03

Затем добавляем в решение проект databaselayer_databaselayer_sqlite.dsp – это проект SqliteDatabaseLayer, который позволяет получить доступ к базам данных SQLite в приложении.

После этого необходимо настроить конфигурации сборки. Открываем Configuration Manager (Build -> Configuration Manager) и устанавливаем для проекта databaselayer_sqlite нужную отладочную и финальную конфигурацию. В нашем примере это Static Unicode Debug Multilib Static и Static Unicode Release Multilib Static.

databaselayerminimal_04

После этого в нашем проекте приложения необходимо настроить пути для поиска заголовочных файлов, файлов библиотек, а также список дополнительных библиотек для сборки проекта.

Для этого в свойствах проекта в разделе C/C++ -> General в свойстве Additional Include Directories прописываем:

1
$(SolutionDir)..\databaselayer\include

В разделе Linker -> General в свойстве Additional Library Directories прописываем:

1
$(SolutionDir)..\databaselayer\lib\vc_lib

В разделе Linker -> Input в свойстве Additional Dependencies указываем список необходимых библиоек:

databaselayerminimal_05

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

Для каждого сервера баз данных в библиотеке DatabaseLayer существует соответствующий класс соединения. В нашем примере мы будем работать с базой данных SQLite. Для этого будем использовать класс SqliteDatabaseLayer.

Для того чтобы открыть базу данных можно использовать два пути:

  • Вызвать конструктор с параметрами и скормить ему путь к базе данных.
  • Использовать конструктор без параметров и метод Open().

В нашем примере будет использоваться первый способ.

Для разрыва соединения с базой данных (или для закрытия файла базы данных) используется метод Close().

В библиотеке DatabaseLayer для обработки ошибок используется механизм исключений. Для обработки ошибок необходимо отлавливать исключение DatabaseLayerException.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <wx/wx.h>
#include <DatabaseLayer.h>
#include <SqliteDatabaseLayer.h>
#include <DatabaseLayerException.h>
 
int main()
{
    int returnCode(0);
    DatabaseLayer * connection(NULL);
    do
    {
        try
        {
            connection = new SqliteDatabaseLayer(wxT("Minimal.sqlite"), false);
        }
        catch(DatabaseLayerException & e)
        {
            returnCode = 2;
            wxPrintf(wxT("%d %s"), e.GetErrorCode(), e.GetErrorMessage().GetData());
        }
    }
    while(false);
    wxDELETE(connection);
    getchar();
    return returnCode;
}

Необходимо помнить, что все ресурсы нужно освобождать руками.

Для выборки данных из таблицы используется метод RunQueryWithResults(), который возвращает указатель но объект DatabaseResultSet. После работы с результатми запроса, объект DatabaseResultSet необходимо обязательно закрыть во избежание утечек памяти. Сделать это можно, вызывав метод DatabaseLayer::CloseResultSet().

Для обхода записей, возвращенных с помощью метода RunQueryWithResults() используется метод DatabaseResultSet::Next().

Для получения значения поля в классе DatabaseResultSet существует соответствующий набор методов – GetResultInt(), GetResultString(), GetResultBool() и т.д. Каждый из этих методов может принимать как имя поля, так и порядковый номер (zero-based).

Для запросов, которые не возвращают список записей (INSERT, DELETE) используется метод RunQuery().

И вот со всем, описанным выше, мы подошли к рассмотрению более сложного примера – приложение открывает базу данных SQLite, проверяет ее на наличие таблиц. Если таблицы не найдены, то приложение создает одну таблицу и заполняет ее данными. После этого происходит выборка данных и отображение результатов выборки в консоли.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <wx/wx.h>
#include <DatabaseLayer.h>
#include <SqliteDatabaseLayer.h>
#include <DatabaseLayerException.h>
 
int main()
{
    int returnCode(0);
    DatabaseLayer * connection(NULL);
    DatabaseResultSet * result(NULL);
    do
    {
        try
        {
            connection = new SqliteDatabaseLayer(wxT("Minimal.sqlite"), false);
            result = connection->RunQueryWithResults(
                wxT("SELECT * FROM sqlite_master WHERE type='table'"));
            if(!result || !result->Next())
            {
                connection->RunQuery(
                    wxT("CREATE TABLE SampleTable \
                        (ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \
                        Name VARCHAR(32))"));
                for(int i = 0; i < 5; i++)
                {
                    connection->RunQuery(wxString::Format(
                        wxT("INSERT INTO SampleTable (Name) VALUES ('%i')"), rand()));
                }
            }
            if(result)
            {
                connection->CloseResultSet(result);
                result = NULL;
            }
            result = connection->RunQueryWithResults(wxT("SELECT * FROM SampleTable"));
            if(!result)
            {
                returnCode = 1;
                break;
            }
            while (result->Next())
            {
                wxPrintf(wxT("%d - %s\r\n"),
                    result->GetResultInt(wxT("ID")),
                    result->GetResultString(wxT("Name")).GetData());
            }
        }
        catch(DatabaseLayerException & e)
        {
            returnCode = 2;
            wxPrintf(wxT("%d %s"), e.GetErrorCode(), e.GetErrorMessage().GetData());
        }
    }
    while(false);
    if(connection)
    {
        if(result) connection->CloseResultSet(result);
    }
    wxDELETE(connection);
    getchar();
    return returnCode;
}

Скачать исходный код примера.

7 Comments

  • roman
    Posted July 1, 2009 at 12:57

    Все отлично, но откуда к примеру взять библиотеки comctl32.lib uuid.lib rpcrt4.lib advapi32.lib wxbase28ud.lib wxmsw28ud_core.lib wxcode_msw28ud_databaselayer_sqlite.lib. В архиве их нет.

  • Post Author
    T-Rex
    Posted July 3, 2009 at 14:58

    comctl32.lib uuid.lib rpcrt4.lib advapi32.lib – стандартные, ставятся с Visual Studio
    wxbase28ud.lib wxmsw28ud_core.lib – при сборке wxWidgets появляются
    wxcode_msw28ud_databaselayer_sqlite.lib – создаются при сборке DatabaseLayer.

  • Семён
    Posted August 4, 2009 at 23:07

    при компиляции mingw-ом я слегка помучался:) разработчики явно его не долюбливают. Чтобы скомпилировать только postgre_sql пришлось править makefile.gcc. В то же время gnumake и VisualStudio позволяют это делать.

    И почему то хидеры в архиве только для sqlite. И чтобы скомпилить всю либу под mingw приходится либо makefile править либо качать исходники всех поддерживаемых СУБД.

    Но в целом всё получилось неплохо и даже все тесты прошли.

  • Sam
    Posted August 5, 2009 at 20:27

    насколько я понял Databaselayer без dll может работать только с SQLite или я заблуждаюсь?
    Я пытаюсь работать с postgres. Следуя доке я конвертнул libpq.dll в libpq.a, а как заставить mingw засунуть эту либу в исполняемый файл понять не могу. Databaselayer компилировал с опциями MONOLITHIC=1, DEBUG=1, WXSHARED=0, SHARED=0…

    p.s. а за что мой предыдущий пост удалили?

  • T-Rex
    Posted August 9, 2009 at 12:22

    ибо качать исходники всех поддерживаемых СУБД.

    Какие такие исходники? Для всего есть заголовки/либы в дистрибутивах СУБД. Для Postgres, MySQL точно есть.

  • T-Rex
    Posted August 9, 2009 at 12:25

    Следуя доке я конвертнул libpq.dll в libpq.a, а как заставить mingw засунуть эту либу в исполняемый файл понять не могу.

    Не конвертнул, а создал import library. Это не одно и тоже. import library просто говорит линкеру что некоторые функции лежат не в исполняемом файле а во внешней DLL. И таскать эту dll надо за собой всегда. Это нормально.
    Хочется распространять прогу одним файлом? Сделай инсталлятор. в NSIS/NISEdit это за минуту делается

  • T-Rex
    Posted August 9, 2009 at 12:28

    p.s. а за что мой предыдущий пост удалили?

    Возможно мне показалось что ты бот 😛

Leave a comment

0.0/5