Форум программистов, компьютерный форум, киберфорум
C++: COM, OLE, ActiveX
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.67/21: Рейтинг темы: голосов - 21, средняя оценка - 4.67
11 / 7 / 5
Регистрация: 12.01.2020
Сообщений: 89
1

Работа с БД: с чего начать

12.01.2020, 15:15. Просмотров 4266. Ответов 72
Метки нет (Все метки)

Есть файл Parik.accdb (Оффис 2016г.), Винда х64, работаю в VS2019. Хочу написать приложение в С++, делающее запрос к БД и выводящее результат в консоль. С чего начать? Нужно ли установить какие-нибудь библиотеки, посмотреть, что показывает Администратор источника данных ODBC (или использовать не ODBC)? Какой шаблон проектов (пустое приложение, приложение MFC, консольное приложение) выбрать?
Являюсь начинающим программистом, возможно, не в тот раздел поместил тему.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.01.2020, 15:15
Ответы с готовыми решениями:

работа с графикой. с чего начать?
Итак,есть консольный морской бой. Возможно ли сделать на него графическую оболочку и что для этого...

Работа с API. С чего начать?
Всем привет! Мне надо написать скрипт который работает с другим сайтом с помощью API. Так как я...

Дипломная работа. С чего начать ?
Привет всем. Получил тему дипломной работы. Построение информационного словаря признаков для...

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

72
5829 / 3967 / 1626
Регистрация: 07.05.2019
Сообщений: 12,313
Записей в блоге: 1
23.01.2020, 21:21 61
Цитата Сообщение от НВВ Посмотреть сообщение
Мне для начала надо было сделать рабочие аргументы для Connection. Со временем я разберусь и укажу нового провайдера.
Провайдер и есть рабочий элемент. Подозреваю, Microsoft.Jet.OLEDB.4.0 уже давно не поддерживается, потому у тебя Open и отваливается

Добавлено через 1 минуту
Цитата Сообщение от НВВ Посмотреть сообщение
Пробовал вносить в аргумент строки подключения названия поставщиков из него, но появляется сообщения, что поставщик не найден.
Потому я тебе и говорил насчёт udl-файлов
0
11 / 7 / 5
Регистрация: 12.01.2020
Сообщений: 89
23.01.2020, 21:23  [ТС] 62
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
потому у тебя Open и отваливается
Нет, сейчас у меня выполняется код до pRSet->Open. Наверняка уже здесь у меня ошибки в аргументах.

Добавлено через 57 секунд
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Потому я тебе и говорил насчёт udl-файлов
С udl засада, надо будет потом тоже разбираться.
0
11 / 7 / 5
Регистрация: 12.01.2020
Сообщений: 89
25.01.2020, 22:47  [ТС] 63
Итак, сейчас код следующий:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
                pConnection.CreateInstance(__uuidof(ADODB::Connection));
                pConnection->Open((L"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\\Parik.mdb;"), _bstr_t(""), _bstr_t(""), 0);
                string a;
                if (pConnection->State == 1) a = "Соединение установлено";
                else a = "Соединение не установлено";
                cout << "Состояние соединения: " << a << "\n";
                    pCommand.CreateInstance(__uuidof(ADODB::Command));
                    pCommand->ActiveConnection = pConnection;
                    pCommand->CommandText = _bstr_t("Select Firm From Enterprise");
                    pCommand->CommandType = ADODB::CommandTypeEnum(1);
                    _variant_t  vtRowsAffected;
                    _variant_t  vtMissing;
                    ADODB::_CommandPtr Comm;
                    Comm = pCommand->Execute(&vtRowsAffected, &vtMissing, ADODB::adCmdText);
После выполнения последней строки консоль выдаёт: "Неправильно определен объект Parameter. Предоставлены несогласованные или неполные сведения". Пробовал в качестве последнего аргумента в последней строке указать 1, то же самое.
0
5829 / 3967 / 1626
Регистрация: 07.05.2019
Сообщений: 12,313
Записей в блоге: 1
27.01.2020, 09:50 64
Цитата Сообщение от НВВ Посмотреть сообщение
После выполнения последней строки консоль выдаёт: "Неправильно определен объект Parameter. Предоставлены несогласованные или неполные сведения". Пробовал в качестве последнего аргумента в последней строке указать 1, то же самое.
Попробуй сделать
C++
1
Comm = pCommand->Execute(nullptr, nullptr, ADODB::adCmdText);
0
11 / 7 / 5
Регистрация: 12.01.2020
Сообщений: 89
27.01.2020, 21:17  [ТС] 65
Сделал, выдало ошибку: "Класс не зарегистрирован" Скорее всего ругается из-за аргументов nullptr, nullptr.
Раньше была ошибка, насколько я понял, из-за последнего аргумента (объект Parameter). Думаю, что в этом направлении надо копать.
0
5829 / 3967 / 1626
Регистрация: 07.05.2019
Сообщений: 12,313
Записей в блоге: 1
27.01.2020, 21:20 66
Цитата Сообщение от НВВ Посмотреть сообщение
Сделал, выдало ошибку: "Класс не зарегистрирован" Скорее всего ругается из-за аргументов nullptr, nullptr.
Нет, не из-за этого
0
11 / 7 / 5
Регистрация: 12.01.2020
Сообщений: 89
28.01.2020, 08:50  [ТС] 67
Крайне обескуражен трудностями, с которыми столкнулся. С одной стороны, если продолжить, то приобрету неоценимый опыт. С другой, может, надо настроить свой комп, чтобы я уже не использовал Provider=Microsoft.Jet.OLEDB.4.0, а использовал провайдера Microsoft.ACE.OLEDB.12.0 или более нового? А может, надо создать класс, который унаследует функционал ADODB, и действовать через функции созданного класса?
Обращаюсь к опытным: вы можете сказать, почему столько геморроя?
0
5829 / 3967 / 1626
Регистрация: 07.05.2019
Сообщений: 12,313
Записей в блоге: 1
28.01.2020, 09:27 68
Цитата Сообщение от НВВ Посмотреть сообщение
Обращаюсь к опытным: вы можете сказать, почему столько геморроя?
Я ж тебе написал в начале, что задачу надо разбить на две части - сначала научится работать с ADO в скриптах, а потом реализовать то же самое на C++. Геморрой в том, что ты не умеешь ни того ни другого и пытаешься сделать всё сразу.
0
11 / 7 / 5
Регистрация: 12.01.2020
Сообщений: 89
28.01.2020, 10:25  [ТС] 69
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
сначала научится работать с ADO в скриптах
- что конкретно выучить, что порекомендуете прочесть?
0
5829 / 3967 / 1626
Регистрация: 07.05.2019
Сообщений: 12,313
Записей в блоге: 1
28.01.2020, 10:47 70
Цитата Сообщение от НВВ Посмотреть сообщение
- что конкретно выучить, что порекомендуете прочесть?
Да просто сделай то, что ты сейчас пытался сделать на javаscript или vbscript, в msdn вроде все примеры под них
0
297 / 102 / 16
Регистрация: 29.06.2019
Сообщений: 957
30.03.2020, 19:08 71
Цитата Сообщение от НВВ Посмотреть сообщение
"Неправильно определен объект Parameter. Предоставлены несогласованные или неполные сведения".
вообще-то Параметрический запрос вида
SELECT f1, f2, f3 FROM tbl WHERE f1=?
и в языке, на котором пишете клиента должен быть синтаксис задать этот '?'
например в vba - это...
в С++ искать не буду...
но, мне кажется, вы используете Cmd не по назначению -
обратите внимание на 3-й пост здесь - и там далее задаётся он, правда на VB...
Visual Basic
1
cmd.Parameters.Append cmd.CreateParameter("id", adSmallInt, adParamInput, , ParamValue)
- а если именно Command всё-таки вам нужен - то найдите способ задать его на C++ и укажите '?' в запросе...
к сожалению, как зделать это на С++ не знаю - не делала...
0
11 / 7 / 5
Регистрация: 12.01.2020
Сообщений: 89
31.03.2020, 15:42  [ТС] 72
Вы, насколько я понял, путаете параметр SQL-запроса и параметры метода Command ADO.
В том коде, про который Вы говорите, действительно, Command используется не по назначению. Я уже разобрался с этим. Теперь код выглядит иначе:
C++
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#pragma warning(disable : 4996)
#include <string>
#include <iostream>
#import "c:/Program Files/Common Files/System/ADO/msado15.dll" rename("EOF","AdoNSEOF")
using namespace std;
using namespace ADODB;//необходимо для макросов AD_BINDING
inline void TESTHR(HRESULT x)
{
    if FAILED(x) _com_issue_error(x);
};
void OpenX();
void PrintProviderError(_ConnectionPtr pConnection);
void PrintComError(_com_error& e);
 
int main1()
{
    if (FAILED(::CoInitialize(NULL)))
        return -1;
 
    OpenX();
    ::CoUninitialize();
}
 
void OpenX()
{
    // Define ADO object pointers.  Initialize pointers on define.  
    // These are in the ADODB:: namespace  
    _RecordsetPtr pRSet = NULL;
    _ConnectionPtr pConnection = NULL;
 
    setlocale(LC_ALL, "Russian");
    _bstr_t strCnn("Provider='Microsoft.ACE.OLEDB.16.0'; Data Source='D:\\Parik.accdb'; ''; ''; 0");
try
    {
        // открываем соединение и набор записей  
        TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
        pConnection->Open(strCnn, "", "", adConnectUnspecified);
        string a;
        if (pConnection->State == 1) a = "Connection enabled";
        else a = "Connection don't enabled";
        printf ("Connection status: ",  a );
        TESTHR(pRSet.CreateInstance(__uuidof(Recordset)));
        pRSet->Open("Select * From Enterprise", _variant_t((IDispatch*)pConnection, true),
            adOpenKeyset, adLockOptimistic, adCmdText);
 
        if (pRSet->State == 1) a = "Recordset enabled";
        else a = "Recordset don't enabled";
        cout << "Recordset status: " << a << "\n";
 
        FieldsPtr pFields;
        FieldPtr pField;
        pFields = pRSet->Fields;
        int nNumFields = pRSet->Fields->Count;
        int nNumRows = pRSet->RecordCount;
        cout << "Количество записей (строк) в RecordSet: " << nNumRows << "\n";
        char* pName;
        int const n = 10;
        char const m = 20;
        char* Arr[n][m];
        int i;
        int k;
        //int a = 0;
        for (i = 0; i < nNumFields; i++)
        {
            pName = new char[pRSet->Fields->Item[(HRESULT)i]->Name.length()];
            strcpy(pName, (LPCSTR)pRSet->Fields->Item[(HRESULT)i]->Name);
            Arr[i][0] = pName;
            fprintf(stderr, "%s                        ", Arr[i][0]);
        }
        cout << "" << "\n";
        pRSet->AbsolutePosition; //устанавливаем курсор в начало
 
        while (!pRSet->AdoNSEOF)
        {
            for (i = 0, k = 0; i < nNumFields; i++, k++)
            {
                cout << _bstr_t(pRSet->Fields->Item[Arr[k][0]]->Value) << "                           ";
                if (k == nNumFields - 1) cout << "\n ";
 
            }
            pRSet->MoveNext();
        }
 
}
    catch (_com_error& e)
    {
        // Display errors, if any. Pass a connection pointer accessed from the Connection.  
        PrintProviderError(pConnection);
        PrintComError(e);
    }
 
    // Clean up objects before exit.  
    if (pRSet)
        if (pRSet->State == adStateOpen)
            pRSet->Close();
    if (pConnection)
        if (pConnection->State == adStateOpen)
            pConnection->Close();
 
    system("PAUSE");
}
 
void PrintProviderError(_ConnectionPtr pConnection)
{
    // Print Provider Errors from Connection object.  
    // pErr is a record object in the Connection's Error collection.  
    ErrorPtr pErr = NULL;
 
    if ((pConnection->Errors->Count) > 0)
    {
        long nCount = pConnection->Errors->Count;
        // Collection ranges from 0 to nCount -1.  
        for (long i = 0; i < nCount; i++)
        {
            pErr = pConnection->Errors->GetItem(i);
            //printf("\t Error number: %x\t%s", pErr->Number, pErr->Description);
            cout << "Error number: " << (pErr->Number, pErr->Description) << "\n";
        }
    }
}
 
void PrintComError(_com_error& e)
{
    _bstr_t bstrSource(e.Source());
    _bstr_t bstrDescription(e.Description());
 
    // Print COM errors.   
    printf("Error\n");
    printf("\tCode = %08lx\n", e.Error());
    //printf("\tCode meaning = %s\n", e.ErrorMessage());
    cout << "Code meaning " << e.ErrorMessage() << "\n";
    printf("\tSource = %s\n", (LPCSTR)bstrSource);
    printf("\tDescription = %s\n", (LPCSTR)bstrDescription);
}
Надо сказать, что все проблемы у меня были из-за операционной системы. После переустановки оной всё сделал сам. Кстати, надо скачать AccessDatabaseEngine_X64, чтобы мой код работал. Это я сделал отсюда. Теперь всё работает: делается запрос к БД и данные таблицы выводятся в консоль.
В настоящий момент работаю над выводом данных таблицы в Windows Forms.

Добавлено через 15 минут
Забыл добавить в код две строки:
C++
1
2
pRSet->Close();
    pConnection->Close();
0
297 / 102 / 16
Регистрация: 29.06.2019
Сообщений: 957
09.04.2020, 11:22 73
поздравляю... спасибо за приложенный код! - поизучаю на досуге
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.04.2020, 11:22

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Работа в интернете, с чего начать?
всем здрасте :) я вот решил занятся заработком в интернете, но не знаю с чего лучше начать. знаю...

Работа со структурами, подскажите с чего начать
Здравствуйте, знатоки ,мне нужна ваша помощь :) Вообщем, мне надо сделать лабораторную по...

Работа со списками, подскажите с чего начать
Работа со списками: в списке целых чисел удалить из каждой группы подряд идущих одинаковых...

Работа с файлами,чтение/запись, не знаю даже с чего начать
У администратора железнодорожных касс хранится информация о свободных местах в поездах дальнего...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
73
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.