Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> DSEL для работы с БД 
:(
    Опции темы
Lazin
Дата 27.6.2009, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Возникла идея создать сабж..

Идея состоит в следующем, допустим у нас есть код, который умеет подключаться к БД, выполнять запрос и получать его результаты, соответственно остается распарсить таблицу результатов запроса и получить коллекцию объектов.

в простейших случаях это просто, так как одному экземпляру объекта, соответствует одна запись в таблице результатов запроса. Если у нас есть объект
Код

struct Employe
{
    std::string name;
    std::string sname;
    int age;
};

и запрос для получения списка этих объектов:
Код

SELECT name, sname, age FROM EmployeTable

то код будет прост и прямолинеен.. но что, если у нас не просто коллекция объектов, а иерархия объектов, и для получения каждого уровня иерархии нужен отдельный запрос, либо запрос один, но он объединяет несколько таблиц? Тогда придется писать код, который преобразует результаты запросов в иерархию объектов.
Код

struct Employe
{
    std::string name;
    std::string sname;
    int age;
};

struct Department
{
    int id;
    std::string name;
    std::vector<Employe> employe_list;

};

Код

SELECT name, sname, age, dep_id FROM EmployeTable ORDER BY dep_id

Код

SELECT id, name FROM DepTable ORDER BY id

в принципе, возможно написать библиотеку, которая позволяла-бы описывать то, как нужно извлекать данные из recordset-ов с результатами запросов, с помощью техники expression templates, а так-же позволяла-бы объединять результаты нескольких запросов в одну структура данных, в данном примере, результаты выполнения 2х селектов, в последовательность Department-ов, каждый их которых содержал бы набор объектов типа Employe, которые ему принадлежат...
код может при этом выглядеть так:
Код

struct Employe
{
    std::string name;
    std::string sname;
    int age;
    
    Employe(std::string name, std::string sname, int age)
        : name(name)
        , sname(sname)
        , age(age)
    {
    }
};

struct Department
{
    int id;
    std::string name;
    std::vector<Person> employe_list;
    
    Department( int id, std::string name)
        : id(id)
        , name(name)
    {
    }
};



namespace detail
{
    using namespace rdb;

    //запрос для получения списка сотрудников, отсортированых по отделам в которых они работают
    struct QueryEmployeList : query<QueryEmployeList>
    {
        std::string get_query_text() const
        {
            return "SELECT name, sname, age, dep_id FROM EmployeTable ORDER BY dep_id";
        }
    };

    // DSEL элементы для анализа результатов запроса
    // каждый из них "знает" из какого именно запроса(точнее результата выполнения этого запроса)
    // он может извлекать данные, а так-же "знает" как их интерпретировать(как int, как string etc)
    field<QueryEmployeList, std::string, 0> const employe_name;
    field<QueryEmployeList, std::string, 1> const employe_sname;
    field<QueryEmployeList, int, 2> const employe_age;
    field<QueryEmployeList, int, 3> const employe_dep;
    
    // запрос списка отделов
    struct QueryDepartmentList : query<QueryDepartmentList>
    {
        std::string get_query_text() const
        {
            return "SELECT id, name FROM DepTable ORDER BY id";
        }
    };
    
    // DSEL elements
    named_field<QueryDepartmentList, int> dep_id("id");
    named_field<QueryDepartmentList, std::string> dep_name("name");
    
    // ф-я для выполняет запросы и по их результатам строит коллекцию объектов
    void get_all_departments(connection& con, std::vector<Department>& dep_list)
    {
        recordset emps = execute_query(con, QueryEmployeList);
        recordset deps = execute_query(con, QueryDepartmentList);

        zip( deps, emps
           , create_a<Department>(dep_id, dep_name)            // create department
           , employe_dep == dep_id                             // while employe_dep == dep_id do
           , append_a( member_a<Department::employe_list>(_1)  // department.push_back( create employe )
                     , create_a<Employe>(employe_name, employe_sname, employe_age))
           , std::back_inserter(dep_list) );
    }
}

//connect db
rdb::connection connection( rdb::vendor::sqlite3, /*connection string*/db_file_name.c_str());

std::vector<Department> deps;
detail::get_all_departments(connection, deps);

Пользователь, предварительно описывает запросы, и элементы для DSL доступа к данным. Ф-я zip - принимает 6 параметров, первые 2 - запросы, первый из них, соответствует более высокому уровню иерархии(Department), второй более низкому(Employe). Далее ф-я zip вызывает первый функтор(3-й параметр), передавая ему в качестве параметра первый recordset, этот функтор должен вернуть объект класса Department. Далее, до тех пор, пока второй функтор(4-й параметр, получает в качестве параметров 2 recordset-a) возвращает true, zip вызывает 5-й функтор, передавая ему в качестве параметров, ранее созданый объект класса Department и второй recordset. Этот функтор создает объект класса Employe и добавляет его в employe_list объекта department. После того как 4-й функтор вернет false, полученый объект класса Department будет записан в контейнер(через итератор), курсор первого recordset-a переместится на следующую запись, и все повториться заново. В результате будем иметь контейнер заполненный данными.
Этот код зависит от того, как запросы возвращают данные, но он может от этого и не зависеть. 

В общем вопрос в том, стали бы вы использовать что-то подобное. Думаю реализовать это вполне возможно, вопрос в том, нужно-ли.. smile 
зы
как делать update-ы я пока не думал, но, если у нас есть все для того, что-бы извлекать данные из recordset-ов и создавать на основе этой информации структуры данных, то обратная задача то-же вполне решаема.. 
PM MAIL Skype GTalk   Вверх
unicuum
  Дата 27.6.2009, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 830
Регистрация: 16.3.2005
Где: Рашка

Репутация: 1
Всего: 8



Цитата(Lazin @  27.6.2009,  15:53 Найти цитируемый пост)
с помощью техники expression templates, а так-же позволяла-бы объединять результаты нескольких запросов в одну структура данных

Напоминает наборы данных в дотнете. Они там являются частичной или полной копией базы данных в оперативной памяти. И им так же доступны все операции и разнообразные выражения. Да, этой техникой пользуются, и думаю хорошей реализацией на C++ тоже будут пользоваться.

А вот другой вариант это структуры данных и их совмещение с базами данных. Например, древовидный список можно представить в виде одной таблицы. Можно его считать из базы в особую древовидную структуру, а можно закешировать в оперативной памяти в том виде, в каком это лежит в базе данных и лишь отображать по иному (MVC и так далее).

Опять же, если мы на языке C++ в программу введём таблицы, поля и прочее, то по аналогии с дотнетом, можно сказать, что у нас получится строгая типизация. Там это делают за счёт наследования от набора данных. Здесь ещё вот в чём вопрос, быстрее ли обращаться к базе, которая зачастую имеет собственные механизмы кэширования, или записывать то, что нам нужно в оперативную память.

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

Добавлено через 3 минуты и 36 секунд
В общем, я так понимаю, тема про отсоединённые и присоединённые объекты, а так же строгая и не строгая типизация в C++. Поправь если неправильно понял мысль. smile 


--------------------
user posted image
обычный день на винграде
PM   Вверх
Lazin
Дата 27.6.2009, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



ах да, еще фишка в том, что к объектам, нет ни каких требований
PM MAIL Skype GTalk   Вверх
Lazin
Дата 27.6.2009, 20:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(unicuum @  27.6.2009,  16:35 Найти цитируемый пост)
Поправь если неправильно понял мысль

ты это о чем вообще?
PM MAIL Skype GTalk   Вверх
unicuum
  Дата 27.6.2009, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 830
Регистрация: 16.3.2005
Где: Рашка

Репутация: 1
Всего: 8



Цитата(Lazin @  27.6.2009,  20:50 Найти цитируемый пост)
ты это о чем вообще? 

Свой же топик хочешь свести к флуду, думаешь он популярнее что-ли от этого станет. smile 


--------------------
user posted image
обычный день на винграде
PM   Вверх
Lazin
Дата 27.6.2009, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(unicuum @  27.6.2009,  21:10 Найти цитируемый пост)
Свой же топик хочешь свести к флуду, думаешь он популярнее что-ли от этого станет

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

Цитата(unicuum @  27.6.2009,  16:35 Найти цитируемый пост)
Напоминает наборы данных в дотнете. Они там являются частичной или полной копией базы данных в оперативной памяти. И им так же доступны все операции и разнообразные выражения. Да, этой техникой пользуются, и думаю хорошей реализацией на C++ тоже будут пользоваться.

мимо

Цитата(unicuum @  27.6.2009,  16:35 Найти цитируемый пост)
А вот другой вариант это структуры данных и их совмещение с базами данных.

что-то вроде. скорее это десериализация объектов, только объект не должен быть унаследован от какого либо класса, короче, полный decoupling того, как данные должны извлекаться из БД от логики приложения..
к примеру, если у меня изменится схема БД, я не хочу просто поправить код приложения в одном месте и все, никакого отношения к кэшированию, дотнету и тд, это не имеет

Цитата(unicuum @  27.6.2009,  16:35 Найти цитируемый пост)
В общем, я так понимаю, тема про отсоединённые и присоединённые объекты, а так же строгая и не строгая типизация в C++. Поправь если неправильно понял мысль

нет, никаких присоединенных и отсоединенных объектов, просто библиотека для извлечения данных

Добавлено через 5 минут и 10 секунд
в общем, это не ORM, просто библиотека для чтения данных
коротко: у нас есть таблицы с результатами выполнения запроса, мы должны на основе этих таблиц создать некую произвольную структуру данных в памяти. Причем эта структура данных не должна ничего "знать" о логике работы с БД. Для этого я предлагаю создать простой DSEL, что-бы иметь возможность описывать то, как преобразовывать данные из одной формы(набор таблиц) в другую(коллекции объектов, иерархии объектов). Соответственно, прежде чем тратить свое время, я решил поинтересоваться, стоит-ли затея потраченного времени.
Собственно все, прошу прощения за то, что так много букв... smile 
PM MAIL Skype GTalk   Вверх
unicuum
  Дата 27.6.2009, 22:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 830
Регистрация: 16.3.2005
Где: Рашка

Репутация: 1
Всего: 8



Цитата(Lazin @  27.6.2009,  21:34 Найти цитируемый пост)
DSEL, что-бы иметь возможность описывать то, как преобразовывать данные из одной формы(набор таблиц) в другую(коллекции объектов, иерархии объектов).

Не вижу никакой разницы, будет у тебя тот же самый адаптер данных с методами Fill и Update, только с шаблоном преобразования в некую структуру данных. Правильное решение зависит не от кода, который ты написал, а от умения работать с базой данных.

Цитата(Lazin @  27.6.2009,  21:34 Найти цитируемый пост)
Соответственно, прежде чем тратить свое время, я решил поинтересоваться, стоит-ли затея потраченного времени.

Если для себя, то стоит, а если для других, то нет. Опять же надо задуматься, нужно ли преобразовывать данные из одной формы в другую. Их дублирование зачастую бывает излишним. К тому же в данном случае лично я воспринимаю созданные в С++ объекты именно как кэш, иначе бы база данных была не нужна.


--------------------
user posted image
обычный день на винграде
PM   Вверх
mes
Дата 28.6.2009, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(unicuum @  27.6.2009,  21:55 Найти цитируемый пост)
лично я воспринимаю созданные в С++ объекты именно как кэш, иначе бы база данных была не нужна. 

скорее отображение результатов запроса БД на типо-безопасные объекты ( работа с которыми в остальной части программы будет проверена компилятором).


Это сообщение отредактировал(а) mes - 28.6.2009, 10:28


--------------------
PM MAIL WWW   Вверх
unicuum
  Дата 28.6.2009, 11:03 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 830
Регистрация: 16.3.2005
Где: Рашка

Репутация: 1
Всего: 8



Цитата(mes @  28.6.2009,  10:28 Найти цитируемый пост)
скорее отображение результатов запроса БД на типо-безопасные объекты ( работа с которыми в остальной части программы будет проверена компилятором).

Так Lazin похоже не хочет их отображать. Я так понимаю из его последнего сообщения ему нужна трансформация данных из базы в объекты и обратно. И всё это заметь, на иных структурах данных и без строгой типизации. Так, конечно, может и интересно сделать это в академических целях, но не очень полезно учитывая мощные механизмы заложенные в базах данных.


--------------------
user posted image
обычный день на винграде
PM   Вверх
Lazin
Дата 28.6.2009, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(mes @  28.6.2009,  10:28 Найти цитируемый пост)
скорее отображение результатов запроса БД на типо-безопасные объекты ( работа с которыми в остальной части программы будет проверена компилятором).

именно smile 
PM MAIL Skype GTalk   Вверх
unicuum
  Дата 28.6.2009, 12:12 (ссылка)    | (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 830
Регистрация: 16.3.2005
Где: Рашка

Репутация: 1
Всего: 8



Цитата(Lazin @  28.6.2009,  11:34 Найти цитируемый пост)
именно smile  

Тогда вообще смысла нет, я бы этим пользоваться не стал.

Добавлено через 7 минут и 35 секунд
Кстати, Lazin, судя по твоему коду у тебя самая обычная строгая типизация, хоть ты и говоришь, нет, да, нет, да. В первый раз когда я тебе это сказал, отнекиваться стал, а теперь пожалуйста. За счёт этого твои объекты и получаются типо-безопасными. На чём бы не программировал, хоть на C++, хоть на Java, хоть на дотнетовских языках, это везде одинаково делается.


--------------------
user posted image
обычный день на винграде
PM   Вверх
Lazin
Дата 29.6.2009, 06:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



профит этого подхода вот в чем. Программируем мы обычно на объектно ориентированых языках программирования, в которых объекты, это сущности, на взаимодействии которых строится программа, моделируют объекты реального мира, или не очень реального... smile 
в реляционной базе данных, информация хранится в другой форме, форме, удобной для хранения, но непригодной для использования в ОО коде, для того, что-бы мы могли работать с данными их БД(я имею ввиду не тупо отсортировать или найти определенную запись, тут можно обойтись написанием одного запроса) нужно создать объекты, причем связи между таблицами должны быть преобразованы в связи между объектами
в общем, обычный подход, мы пишем код, преобразующий результаты запроса в объекты, получается обычно что-то вроде этого:
Код

....
while (!recset1->EOF)
{
    Department dep(
        recset1->Field(_b_str("ID"))->AsInteger(),
        recset2->Field(_b_str("Name"))->AsString() );

    while(!recset2->EOF && recset2->Field(_b_str("dep_id")) == dep.id)
    {
         Employe emp(
              recset2->Field( _b_str("Name") ),
              recset2->Field( _b_str("SName") ),
              recset2->Field( _b_str("age") ) );
         dep.employe_list(emp);
         recset2->MoveNext();
    }
    *out++ = dep;
    recset1->MoveNext();
};


я предлагаю этот код сгенирировать с помощью шаблонов, может получиться что-то вроде этого:
Код

zip_view<...>
  view ( deps, emps
            , create_a<Department>(dep_id, dep_name) 
            , employe_dep == dep_id                            
            , append_a( member_a<Department::employe_list>(_1) 
                      , create_a<Employe>(employe_name, employe_sname, employe_age)) );

std::copy(std::back_inserter(container), view.begin(), view.end());



Цитата(unicuum @  28.6.2009,  12:12 Найти цитируемый пост)
В первый раз когда я тебе это сказал, отнекиваться стал, а теперь пожалуйста
без обид, но ты вообще какой-то бред несешь...

Это сообщение отредактировал(а) Lazin - 29.6.2009, 06:12
PM MAIL Skype GTalk   Вверх
xvr
Дата 29.6.2009, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



У меня дежавю, или этот вопрос уже поднимался? Какая то библиотека для обеспечения функциональности все равно понадобится, и если для ее применения потребуется не наследовать объекты от нее, а заворачивать их в нее (с помощью шаблонов) разница не очень большая.
Кроме того, это 'заворачивание' должно быть 'live' - иначе при заполнении этих шаблонов будет выкачанна вся база данных одним куском  smile 
PM MAIL   Вверх
unicuum
  Дата 29.6.2009, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 830
Регистрация: 16.3.2005
Где: Рашка

Репутация: 1
Всего: 8



Цитата(Lazin @  29.6.2009,  06:10 Найти цитируемый пост)
без обид, но ты вообще какой-то бред несешь...

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


--------------------
user posted image
обычный день на винграде
PM   Вверх
jonie
Дата 29.6.2009, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 15
Всего: 118



Lazin зацени подход к параметрам в запросах - http://sqlitepp.berlios.de/#binders
мб наведет на какие-то другие мысли... а-то все на одно смотреть негоже)


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0775 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.