Программирование на Visual C++. Архив рассылки
Шрифт:
Второй параметр функции OpenEx – набор битовых флагов, объединённых логическим "ИЛИ". Вот некоторые из них:
• CDatabase::openReadOnly – открыть БД в режиме "только для чтения".
• CDatabase::noOdbcDialog – никогда не выводить диалог, запрашивающий дополнительную информацию о соединении.
• CDatabase::forceOdbcDialog – всегда выводить диалог, запрашивающий информацию о соединении. Этот режим уместен, если во время написания программы не известно, с какой именно базой данных она будет работать.
По умолчанию (если второй параметр OpenEx не задан или равен 0) база данных открывается в режиме "чтение и запись", а диалог
Выборка данных из таблицы
Работая с ODBC, программа получает данные, извлекаемые из БД, в виде множества записей (recordset). Каждая запись содержит набор полей. В любой заданный момент времени программа может работать только с одной записью (она называется текущей). Используя функции ODBC, можно перемещаться от одной записи к другой. Для удобства каждое поле в результирующем множестве обычно связывается с переменной, которую программа использует для чтения и модификации значения соответствующего поля. Тем не менее, связывать поля с переменными в общем случае необязательно.
В MFC для работы с множеством записей предназначен класс CRecordset. Как правило, этот класс не используется в программе напрямую. Вместо этого от него порождают новые классы, переменные-члены которых и связываются с полями множества записей. Само связывание происходит в виртуальной функции CRecordset::DoFieldExchange, которая переопределяется в производном классе; эта же функция осуществляет обмен данных между полями записи и переменными класса. Множество записей создаётся функцией CRecordset::Open, а перемещение от одной записи к другой осуществляется посредством функций Move, MoveNext, MovePrev и т. п.
Пример
Рассмотрим небольшой пример. Допустим, в базе данных содержится таблица tPeople с полями Name (типа строка из 50 символов) и DateOfBirth (типа дата/время), и мы хотим напечатать на экране её содержимое. Сперва создаём новый класс, порождённый от CRecordset:
Для каждого поля в таблице tPeople мы объявили переменную соответствующего типа. Так, поле Name хранится как строка, поэтому m_Name имеет тип CString. DateOfBirth - это дата, поэтому m_DateOfBirth - переменная типа CTime. Обратите внимание, что в переменную m_nFields (CPeople наследует её от CRecordset) необходимо записать количество полей таблицы (это значение необходимо MFC, чтобы правильно построить запрос). Теперь реализуем функцию DoFieldExchange, в которой происходит связывание полей таблицы с переменными нашего класса CPeople.
Вызов SetFieldType
Каждый из макросов, используемых в DoFieldExchange, имеет префикс "RFX_". Существует несколько версий этих макросов – по одному на каждый основной тип. Наборы параметров у них несколько отличаются, но первые три параметра совпадают у всех макросов: указатель на объект класса CFieldExchange (нужно просто передать указатель, полученный от MFC), имя поля во множестве записей и ссылка на переменную, которая будет с этим полем связана.
Итак, создание класса CPeople закончено, и можно использовать его для доступа к таблице tPeople. Вот фрагмент, который печатает на экране её содержимое.
:
:
Здесь нужно обратить внимание на несколько моментов. Во-первых, как мы помним, прежде чем работать с базой данных, необходимо установить соединение с ней. Это делается с использованием уже знакомой нам функцией CDatabase::OpenEx. Во-вторых, указатель на соединение нужно передать конструктору класса CPeople, чтобы данные извлекались именно из нужной нам базы данных.
Теперь рассмотрим параметры функции CRecordset::Open. Первый параметр задаёт тип результирующего множества записей. Можно задавать следующие типы:
• CRecordset::forwardOnly – множество записей, доступное только для чтения и по которому можно перемещаться только вперёд.
• CRecordset::snapshot – множество записей, по которому можно перемещаться в любом направлении. Изменения, внесённые в БД после создания такого множества, в нём не отражаются.
• CRecordset::dynaset – похоже на предыдущее, но любые изменения записи в БД будут видны после повторной выборки этой записи. Новые записи, добавленные в БД после создания такого множества, в нём не отражаются.
• CRecordset::dynamic – самое ресурсоёмкое множество. Любые изменения, внесённые в БД после его открытия, будут в нём отражены. Не поддерживается многими драйверами.
Если драйвер не поддерживает запрошенный тип множества записей, MFC возбудит исключение.
Второй параметр функции CRecordset::Open используется для передачи имени таблицы или запроса, на основе которого будет построено множество записей. MFC сама определит, что именно ей передали. У функции CRecordset::Open есть также третий параметр – который во многих случаях можно не указывать. За его описанием можно обратиться к документации.