Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Добавление данных в базу (mfc)

407
08 марта 2006 года
shupik
160 / / 15.09.2004
Господа программеры! У меня возник такой вопрос - как проще всего в моем случае добавить данные в базу данных (mdb) средствами MFC? Считать их довольно несложно - приведу даже фрагмент кода:
CDatabase base;
CString sDriver,sDsn,sSql,place;
CLoadDataFromExcel readingDriver;
sDriver = readingDriver.GetExcelDriver();
sDsn.Format("ODBC;DRIVER={%s};DSN='';DBQ=%s",sDriver,"1.mdb");
TRY
{
base.Open(NULL,false,false,sDsn);
CRecordset recset( &base );
sSql = "SELECT * FROM Данные";
recset.Open(CRecordset::forwardOnly,sSql,CRecordset::readOnly);
while( !recset.IsEOF())
recset.GetFieldValue("Type",place);
recset.MoveNext();
}
recset.Close();
base.Close();
}
CATCH(CDBException, e)
{

CDialog errorDatabase;
errorDatabase.MessageBox("Ошибка базы:"+e->m_strError,"Критическая ошибка",MB_OK|MB_ICONERROR);
}
END_CATCH;

Вот не могу понять, как, во-первых, открывать базу для изменения (имеется ввиду строка recset.Open(CRecordset::forwardOnly,sSql,CRecordset::readOnly); ) и как при добавлении данных передать эти самые данные в соответствующие поля? Ну, например:
if(recset.CanAppend())
{
recset.AddNew();
recset.Type="Имя";
recset.Update();
}
Такой вариант не проходит - компилятор ругается, что нет такого свойства - Type. Но как в таком случае поступить? В VB, насколько я помню, можно было написать: recset!Type = ... А что делать в VC++? Заранее спасибо.
7.9K
08 марта 2006 года
uki_
122 / / 26.01.2006
Чтоб компилятор видел поле Type, нужно породить класс от CRecordSet.

1. Ctrl+W (вызов Class Wizard)
2. Страница Message Maps, кнопка Add Class(New...)
3. Выбрать базовой класс CRecordSet
...дальше думаю понятно.

И recset должен быть экз. этого класса.
324
09 марта 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by uki_
Чтоб компилятор видел поле Type, нужно породить класс от CRecordSet.

1. Ctrl+W (вызов Class Wizard)
2. Страница Message Maps, кнопка Add Class(New...)
3. Выбрать базовой класс CRecordSet
...дальше думаю понятно.

И recset должен быть экз. этого класса.



Также можно через SQL, INSERT INTO и ExecuteSQL

7.3K
10 марта 2006 года
LamerMFC
48 / / 17.09.2005
Цитата:
Originally posted by AndreySar
Также можно через SQL, INSERT INTO и ExecuteSQL



согласен

2shupik

забудь про CRecordset - это всего лишь отображение записей в класс на основе твоего запроса, добовлять, удалять, обновлять только через CDatabase. например удаление:
...
CDatabase dbName;
...(OPEN DB)
CString sql("DELETE FROM name WHERE id_name=1 AND id_name=2");

dbName.ExecuteSQL(sql);

удаляем из базы данных имена с id равными 1 и 2

точно так же и обновление и добавление.

добавление

...

sql.Format("INSERT INTO name(ordername,name) VALUES (%d, '%s')", SomeI, strSomeName);
dbName.ExecuteSQL(sql);

Добавление в базу записи с именем strSomeName и с порядковым номером SomeI. САМОЕ ГЛАВНОЕ НЕ ЗАБУДЬ ПОСТАВИТЬ ОДИНАРНЫЕ КОВЫЧКИ КОГДА ДОБАВЛЯЕШЬ СТРОКУ!!!! ('%s')

324
10 марта 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by LamerMFC
согласен

2shupik

забудь про CRecordset - это всего лишь отображение записей в класс на основе твоего запроса, добовлять, удалять, обновлять только через CDatabase.



Ты не совсем прав. Если сделать класс, производный от CRecordset, то можно добавлять и модифицировать данные таблицы. CRecordset без наследования такую возможность не предоставляет

407
10 марта 2006 года
shupik
160 / / 15.09.2004
Цитата:
Originally posted by LamerMFC
согласен

2shupik

забудь про CRecordset - это всего лишь отображение записей в класс на основе твоего запроса, добовлять, удалять, обновлять только через CDatabase. например удаление:
...
CDatabase dbName;
...(OPEN DB)
CString sql("DELETE FROM name WHERE id_name=1 AND id_name=2");

dbName.ExecuteSQL(sql);

удаляем из базы данных имена с id равными 1 и 2

точно так же и обновление и добавление.

добавление

...

sql.Format("INSERT INTO name(ordername,name) VALUES (%d, '%s')", SomeI, strSomeName);
dbName.ExecuteSQL(sql);

Добавление в базу записи с именем strSomeName и с порядковым номером SomeI. САМОЕ ГЛАВНОЕ НЕ ЗАБУДЬ ПОСТАВИТЬ ОДИНАРНЫЕ КОВЫЧКИ КОГДА ДОБАВЛЯЕШЬ СТРОКУ!!!! ('%s')



Спасибо большое, так действительно быстро и удобно. Единственное, что хотелось уточнить - а как редактировать запись таким методом ? В этом случае следует писать вот так: EDIT INTO name(...) VALUES (...) ?

324
10 марта 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by shupik
Спасибо большое, так действительно быстро и удобно. Единственное, что хотелось уточнить - а как редактировать запись таким методом ? В этом случае следует писать вот так: EDIT INTO name(...) VALUES (...) ?



 
Код:
UPDATE Table_name  
SET Field_Name = 'bla-bla-bla'  
WHERE ID = 1;
407
13 марта 2006 года
shupik
160 / / 15.09.2004
Цитата:
Originally posted by shupik
Спасибо большое, так действительно быстро и удобно. Единственное, что хотелось уточнить - а как редактировать запись таким методом ? В этом случае следует писать вот так: EDIT INTO name(...) VALUES (...) ?



Еще одна сложность возникла - нужно удалять записи из базы не по какому-то фильтру (скажем, все записи с id таким-то), а следующим образом: есть ListCtrl, в который я загружаю все записи из базы. И теперь устанавливая курсор на определенную позицию этого списка, я хочу удалить именно эту запись. Как собственно БД сообщить, какую именно запись я намерен удалить? Ведь список может быть отсортирован в любую сторону. Нужно какое-то поле в базу завести, счетчик? И потом по этом счетчику ориентироваться? Или проще извлечь из списка текущую строку, разложить по полям и передать: DELETE FROM база WHERE поле1="значение_первого_поля" AND поле2= "значение_второго_поля"? Подскажите, пожалуйста, как бы здесь грамотно поступить.

324
13 марта 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by shupik
Еще одна сложность возникла - нужно удалять записи из базы не по какому-то фильтру (скажем, все записи с id таким-то), а следующим образом: есть ListCtrl, в который я загружаю все записи из базы. И теперь устанавливая курсор на определенную позицию этого списка, я хочу удалить именно эту запись. Как собственно БД сообщить, какую именно запись я намерен удалить? Ведь список может быть отсортирован в любую сторону. Нужно какое-то поле в базу завести, счетчик? И потом по этом счетчику ориентироваться? Или проще извлечь из списка текущую строку, разложить по полям и передать: DELETE FROM база WHERE поле1="значение_первого_поля" AND поле2= "значение_второго_поля"? Подскажите, пожалуйста, как бы здесь грамотно поступить.



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

407
13 марта 2006 года
shupik
160 / / 15.09.2004
Цитата:
Originally posted by AndreySar
Проще всего каждой записи задать уникальный идентификатор, т.к. в WHERE тебе надо будет передевать значение каждого поля, потому что записи в базе могут отличаться на значение всего одного поля.



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

7.3K
14 марта 2006 года
LamerMFC
48 / / 17.09.2005
Цитата:
Originally posted by shupik
Получается, в моем ListCtrl всегда должен присутствовать дополнительный столбец со значениями уникального идентификатора? А скрыть его от посторонних глаз никак не удастся?



1) можно сделать рядом с ствоим основным списком еще один список в котором будут id элементов из основного списка. только добавлять в него элементы необходимо так же как и в основной список. потом вызываешь при инициализации диалога ф-цию GetDlgItem(IDC_LIST_ID)->ShowWindow(SW_HIDE) и список с id скрывается.

2) (как сделал я после многих лет мучения с первым вариантом) пишешь производный класс от CListBox, разрисовываешь как тебе нравится потом делаешь дополнительное поле скажем типа int для каждого айтема и хранишь в этом поле любую информацию в том числе и id элементов таблици.

324
14 марта 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by LamerMFC
1) можно сделать рядом с ствоим основным списком еще один список в котором будут id элементов из основного списка. только добавлять в него элементы необходимо так же как и в основной список. потом вызываешь при инициализации диалога ф-цию GetDlgItem(IDC_LIST_ID)->ShowWindow(SW_HIDE) и список с id скрывается.
2) (как сделал я после многих лет мучения с первым вариантом) пишешь производный класс от CListBox, разрисовываешь как тебе нравится потом делаешь дополнительное поле скажем типа int для каждого айтема и хранишь в этом поле любую информацию в том числе и id элементов таблици.



У себя я просто сделал одно поле нулевой ширины и заносил туда ID строки. Еще запретил изменять его ширину. Для пользователя оно не видно и никак не обрабатывается

407
14 марта 2006 года
shupik
160 / / 15.09.2004
Цитата:
Originally posted by AndreySar
У себя я просто сделал одно поле нулевой ширины и заносил туда ID строки. Еще запретил изменять его ширину. Для пользователя оно не видно и никак не обрабатывается



Спасибо - идея отличная. Только вот у меня не ListBox и не пойму, как в ListCtrl вытянуть номер выделенной строки. В ListBox я делал примерно так:
CListBox m_InputList;
CString st;
int ab=m_InputList.GetCurSel();
m_InputList.GetText(ab,st);

А с ListCtrl такой фокус не проходит. Какой из его методов делает нечто похожее?

15K
15 марта 2006 года
hadush
7 / / 14.03.2006
Цитата:
Originally posted by shupik
Спасибо - идея отличная. Только вот у меня не ListBox и не пойму, как в ListCtrl вытянуть номер выделенной строки. В ListBox я делал примерно так:
CListBox m_InputList;
CString st;
int ab=m_InputList.GetCurSel();
m_InputList.GetText(ab,st);

А с ListCtrl такой фокус не проходит. Какой из его методов делает нечто похожее?



Вот так например:

Код:
void CKlientDlg::OnClickListKlient(NMHDR* pNMHDR, LRESULT* pResult)
{  
    POSITION p = m_listKlient.GetFirstSelectedItemPosition();
//CListCtrl m_listKlient;
    int nSelected = m_listKlient.GetNextSelectedItem(p);
    CString str;
    str.Format(_T("%s"), m_listKlient.GetItemText(nSelected, 7));
//7- номер столбца в котором ты хранишь ID строки
    m_klientId = atol(str);
// long m_klientId; Теперь эта переменная сожержит ID
}
7.3K
20 марта 2006 года
LamerMFC
48 / / 17.09.2005
Цитата:
Originally posted by AndreySar
У себя я просто сделал одно поле нулевой ширины и заносил туда ID строки. Еще запретил изменять его ширину. Для пользователя оно не видно и никак не обрабатывается



ну это понятно, а если у тебя CListBox а не СListCtrl?

7.9K
20 марта 2006 года
uki_
122 / / 26.01.2006
Цитата:
Originally posted by LamerMFC
ну это понятно, а если у тебя CListBox а не СListCtrl?

С каждым элементом CListBox/CListCtrl может быть связано DWORD значение.
GetItemData/SetItemData.
Обычно для сохранения ID записей используют эту возможность.

Для сохранения указателей есть еще GetItemDataPtr/SetItemDataPtr.

7.3K
21 марта 2006 года
LamerMFC
48 / / 17.09.2005
Цитата:
Originally posted by uki_
С каждым элементом CListBox/CListCtrl может быть связано DWORD значение.
GetItemData/SetItemData.
Обычно для сохранения ID записей используют эту возможность.

Для сохранения указателей есть еще GetItemDataPtr/SetItemDataPtr.



ликбез одним словом.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог