Здр всем.
В базе MS Access есть две таблицы:
first:
id LONG — pk
body CHAR[40]
second:
fid LONG — fk
info CHAR[120]
Задача — проверить наличие в базе записей с определенным id и при отсутствии вставить новую запись в
second. C использованием OLE DB это будет выглядеть:
class CGenericAccessor
{
public:
LONG m_id;
TCHAR m_info[120];
DBSTATUS m_dwidStatus;
DBSTATUS m_dwinfoStatus;
BEGIN_ACCESSOR_MAP(CGenericAccessor, 2)
BEGIN_ACCESSOR(0, true)
COLUMN_ENTRY(1, m_id)
END_ACCESSOR()
BEGIN_ACCESSOR(1, false)
COLUMN_ENTRY_STATUS(1, m_id, m_dwidStatus)
COLUMN_ENTRY_STATUS(2, m_info, m_dwinfoStatus)
END_ACCESSOR()
END_ACCESSOR_MAP()
DEFINE_COMMAND_EX(CGenericAccessor, L"SELECT id AS id FROM first WHERE id = ? UNION SELECT fid FROM second WHERE fid = ?");
BEGIN_PARAM_MAP(CGenericAccessor)
SET_PARAM_TYPE(DBPARAMIO_INPUT)
COLUMN_ENTRY(1, m_id)
SET_PARAM_TYPE(DBPARAMIO_INPUT)
COLUMN_ENTRY(2, m_id)
END_PARAM_MAP()
};
...
CCommand<CAccessor<CGenericAccessor>> cmd;
Соответственно, код проверки что-то вроде этого:
...
bool bReturn = false;
cmd.m_id = lChecking;
HRESULT hr = cmd.Open(session);
CHECK_HRESULT(hr);
while ((hr = cmd.MoveNext()) == S_OK) {
bReturn = true;
break;
}
cmd.Close();
cmd.ReleaseCommand();
return (bReturn);
...
И вставка:
CDBPropSet dbRowset(DBPROPSET_ROWSET);
dbRowset.AddProperty(DBPROP_IRowsetChange, true);
dbRowset.AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_INSERT);
cmd.Open(m_session, _T("SELECT fid, info FROM second") , &dbRowset);
CHECK_HRESULT(hr);
cmd.m_id = lInsert;
::_tcscpy_s(cmd.m_info, _countof(m_cmd.m_info), _T("Information"));
cmd.m_dwidStatus = DBSTATUS_S_OK;
cmd.m_dwinfoStatus = DBSTATUS_S_OK;
hr = cmd.Insert(1);
CHECK_HRESULT(hr);
cmd.Close();
cmd.ReleaseCommand();
Теперь сам собственно сам вопрос: При использовании "MS OLE DB Provider for ODBC Drivers" этот Accessor работает прекрасно, но при использовании "MS Jet 4.0 OLE DB Provider" вылезает ошибка (выделено болдом) о невозможности column binding'а в карте второго Accessor'а. Как победить этот провайдер с одним классом CGenericAccessor?
P.S.
Переделал под два разных Accessor'a — все работает с двумя провайдерами... Но лишний класс...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Здравствуйте, Figaro, Вы писали:
F>Теперь сам собственно сам вопрос: При использовании "MS OLE DB Provider for ODBC Drivers" этот Accessor работает прекрасно, но при использовании "MS Jet 4.0 OLE DB Provider" вылезает ошибка (выделено болдом) о невозможности column binding'а в карте второго Accessor'а. Как победить этот провайдер с одним классом CGenericAccessor?
F>P.S.
F>Переделал под два разных Accessor'a — все работает с двумя провайдерами... Но лишний класс...
Согласно MSDN (
Using Multiple Accessors on a Rowset) есть 3 возможных сценария, требующих использования multiple accessors. Ваш случай в них не попадает, так что использование двух accessor-ов это вполне логичное решение.
По сути самой проблемы — скорее всего это очередной баг OLEDB классов. Провайдер для ODBC отличается тем, что поддерживает большинство свойств и интерфейсов, используемых OLEDB классами, которые могут не поддерживаться другими провайдерами. Пример — DBMEMOWNER_PROVIDEROWNED.