OLE DB and Accessors (MS ACCESS)
От: Figaro Россия  
Дата: 20.08.09 13:38
Оценка:
Здр всем.

В базе MS Access есть две таблицы:
first:
second:

Задача — проверить наличие в базе записей с определенным 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>>
Re: OLE DB and Accessors (MS ACCESS)
От: algol Россия about:blank
Дата: 24.08.09 12:16
Оценка: 2 (1)
Здравствуйте, 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.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.