Упрощение доступа к данным с помощью атрибутов базы данных
В этом разделе показано использование атрибутов базы данных для упрощения операций с базой данных.
Основным способом доступа к информации из базы данных является создание класса команды (или таблицы) и класса записи пользователя для определенной таблицы в базе данных. Атрибуты базы данных упрощают некоторые объявления шаблона, которые вы ранее сделали.
Чтобы продемонстрировать использование атрибутов базы данных, в следующих разделах показаны две эквивалентные объявления таблиц и классов записей пользователей: первый использует атрибуты и второй использует шаблоны OLE DB. Такой код объявления обычно помещается в файл заголовка с именем таблицы или объекта команды, например Authors.h.
По сравнению с двумя файлами можно увидеть, сколько проще использовать атрибуты. Среди различий:
Используя атрибуты, необходимо объявить только один класс:
CAuthors
в то время как с шаблонами необходимо объявить два:CAuthorsNoAttrAccessor
иCAuthorsNoAttr
.Вызов
db_source
в версии атрибута эквивалентенOpenDataSource()
вызову в объявлении шаблона.Вызов
db_table
в версии атрибута эквивалентен следующему объявлению шаблона:class CAuthorsNoAttr : public CTable<CAccessor<CAuthorsNoAttrAccessor>>
Вызовы
db_column
в версии атрибута эквивалентны сопоставлению столбцов (смBEGIN_COLUMN_MAP ... END_COLUMN_MAP
.) в объявлении шаблона.
Атрибуты внедряют объявление класса записей пользователя для вас. Класс записей пользователя равен CAuthorsNoAttrAccessor
в объявлении шаблона. Если класс CAuthors
таблицы имеет имя, внедренный класс записей пользователя называется CAuthorsAccessor
, и его объявление можно просмотреть только в внедренном коде. Дополнительные сведения см. в разделе "Классы записей пользователей с внедрением атрибутов" в пользовательских записях.
В атрибутах и шаблонном коде необходимо задать свойства набора строк с помощью CDBPropSet::AddProperty
.
Сведения об атрибутах, рассмотренных в этом разделе, см. в разделе "Атрибуты потребителя OLE DB".
Примечание.
Для компиляции приведенных ниже примеров требуются следующие include
инструкции:
#include <atlbase.h> #include <atlplus.h> #include <atldbcli.h>
Объявление таблицы и метода доступа с помощью атрибутов
Следующий код вызывает db_source
и db_table
класс таблицы. db_source
указывает используемый источник данных и подключение. db_table
внедряет соответствующий код шаблона для объявления класса таблицы. db_column
укажите карту столбцов и введите объявление метода доступа. Атрибуты потребителей OLE DB можно использовать в любом проекте, поддерживающем ATL.
Ниже приведено объявление таблицы и метода доступа с помощью атрибутов:
//////////////////////////////////////////////////////////////////////
// Table and accessor declaration using attributes
// authors.h
//////////////////////////////////////////////////////////////////////
// Table class declaration
// (Note that you must provide your own connection string for db_source.)
[
db_source(L"your connection string"),
db_table("Authors")
]
class CAuthors
{
public:
DBSTATUS m_dwAuIDStatus;
DBSTATUS m_dwAuthorStatus;
DBSTATUS m_dwYearBornStatus;
DBLENGTH m_dwAuIDLength;
DBLENGTH m_dwAuthorLength;
DBLENGTH m_dwYearBornLength;
[db_column("1", status = "m_dwAuIDStatus", length = "m_dwAuIDLength")] LONG m_AuID;
[db_column("2", status = "m_dwAuthorStatus", length = "m_dwAuthorLength")] TCHAR m_Author[51];
[db_column("3", status = "m_dwYearBornStatus", length = "m_dwYearBornLength")] SHORT m_YearBorn;
void GetRowsetProperties(CDBPropSet* pPropSet)
{
pPropSet->AddProperty(DBPROP_CANFETCHBACKWARDS, true);
pPropSet->AddProperty(DBPROP_CANSCROLLBACKWARDS, true);
pPropSet->AddProperty(DBPROP_IRowsetChange, true);
}
};
Объявление таблицы и метода доступа с помощью шаблонов
Ниже приведено объявление таблицы и метода доступа с помощью шаблонов.
//////////////////////////////////////////////////////////////////////
// Table and user record class declaration using templates
// authors.h
//////////////////////////////////////////////////////////////////////
// User record class declaration
class CAuthorsNoAttrAccessor
{
public:
DWORD m_dwAuIDStatus;
DWORD m_dwAuthorStatus;
DWORD m_dwYearBornStatus;
DWORD m_dwAuIDLength;
DWORD m_dwAuthorLength;
DWORD m_dwYearBornLength;
LONG m_AuID;
TCHAR m_Author[51];
SHORT m_YearBorn;
void GetRowsetProperties(CDBPropSet* pPropSet)
{
pPropSet->AddProperty(DBPROP_CANFETCHBACKWARDS, true);
pPropSet->AddProperty(DBPROP_CANSCROLLBACKWARDS, true);
pPropSet->AddProperty(DBPROP_IRowsetChange, true);
}
HRESULT OpenDataSource()
{
CDataSource _db;
HRESULT hr;
hr = _db.OpenFromInitializationString(L"your connection string");
if (FAILED(hr))
{
#ifdef _DEBUG
AtlTraceErrorRecords(hr);
#endif
return hr;
}
return m_session.Open(_db);
}
void CloseDataSource()
{
m_session.Close();
}
operator const CSession&()
{
return m_session;
}
CSession m_session;
BEGIN_COLUMN_MAP(CAuthorsNoAttrAccessor)
COLUMN_ENTRY_LENGTH_STATUS(1, m_AuID, m_dwAuIDLength, m_dwAuIDStatus)
COLUMN_ENTRY_LENGTH_STATUS(2, m_Author, m_dwAuthorLength, m_dwAuthorStatus)
COLUMN_ENTRY_LENGTH_STATUS(3, m_YearBorn, m_dwYearBornLength, m_dwYearBornStatus)
END_COLUMN_MAP()
};
class CAuthorsNoAttr : public CTable<CAccessor<CAuthorsNoAttrAccessor>>
{
public:
HRESULT OpenAll()
{
HRESULT hr;
hr = OpenDataSource();
if (FAILED(hr))
return hr;
__if_exists(GetRowsetProperties)
{
CDBPropSet propset(DBPROPSET_ROWSET);
__if_exists(HasBookmark)
{
propset.AddProperty(DBPROP_IRowsetLocate, true);
}
GetRowsetProperties(&propset);
return OpenRowset(&propset);
}
__if_not_exists(GetRowsetProperties)
{
__if_exists(HasBookmark)
{
CDBPropSet propset(DBPROPSET_ROWSET);
propset.AddProperty(DBPROP_IRowsetLocate, true);
return OpenRowset(&propset);
}
}
return OpenRowset();
}
HRESULT OpenRowset(DBPROPSET *pPropSet = NULL)
{
HRESULT hr = Open(m_session, "Authors", pPropSet);
#ifdef _DEBUG
if(FAILED(hr))
AtlTraceErrorRecords(hr);
#endif
return hr;
}
void CloseAll()
{
Close();
CloseDataSource();
}
};