Поделиться через


Использование нескольких методов доступа в наборе строк

Использование нескольких методов доступа требуется, как правило, в трех случаях:

  • Многократное считывание/запись наборов строк. В этом сценарии у таблицы имеется первичный ключ. Вам необходимо иметь возможность считывания всех столбцов в строке, в том числе первичного ключа. Вам также необходимо иметь возможность записи данных во все столбцы, кроме первичного ключа (поскольку запись в столбец первичного ключа невозможна). В этом случае вы создаете два метода доступа:

    • В методе доступа 0 содержатся все столбцы.

    • В методе доступа 1 содержатся все столбцы, кроме первичного ключа.

  • Производительность. В этом сценарии в нескольких столбцах содержится большой объем данных, например, графические, звуковые файлы или видеоклипы. При каждом переходе в строку не следует извлекать столбец с файлом большого объема, поскольку это может снизить производительность приложения.

    Тогда создаются отдельные методы доступа, где в первом методе доступа обрабатываются все столбцы кроме одного с большим объемом данных, а данные из этих столбцов извлекаются автоматически; это метод автоматического доступа. Второй метод извлекает только данные из столбца с большим объемом данных, при этом извлечение из этого столбца не происходит автоматически. Можно использовать и другие методы обновления или доставки данных по требованию.

    • Метод доступа 0 является автоматическим; он извлекает данные из всех столбцов кроме одного с большим объемом данных.

    • Метод доступа 1 не является автоматическим; он извлекает данные из столбца с большим объемом данных.

    Чтобы указать способ обработки для этого метода, добавьте аргумент auto.

  • Несколько столбцов ISequentialStream. В этом сценарии обрабатывается несколько столбцов с данными ISequentialStream. При этом каждый метод доступа ограничен одним потоком данных ISequentialStream. Для решения этой проблемы создайте несколько методов доступа, в каждом из которых будет по одному указателю ISequentialStream.

Обычно методы доступа создаются с помощью макросов BEGIN_ACCESSOR и END_ACCESSOR. Можно также использовать атрибут db_accessor. Методы доступа описываются далее в разделе Записи пользователя.) С помощью макросов или атрибута можно указать, является ли метод доступа автоматическим или нет:

  • При использовании автоматического метода доступа перенесите методы, например, MoveFirst, MoveLast, MoveNext и MovePrev для автоматического извлечения данных из всех указанных столбцов. Метод доступа 0 должен быть автоматическим.

  • При использовании неавтоматического метода доступа извлечение не начнется до тех пор, пока явно не будет вызван метод, например, Update, Insert, Fetch или Delete. В описанном выше сценарии возможно не потребуется извлечение данных из всех столбцов при каждом переходе. Можно разместить несколько столбцов в отдельный метод доступа и определить его как неавтоматический, как показано ниже.

В следующем примере используется несколько методов доступа при считывании и записи данных в таблицу jobs базы данных SQL Server с именем pubs. Это наиболее типичный пример использования нескольких методов доступа; см. приведенный выше скрипт "многократное считывание/запись наборов строк".

Класс пользовательской записи определяется следующим образом. В нем определены два метода: метод доступа 0 отвечает только за обработку столбца первичного ключа (ID), а метод доступа 1 — за обработку других столбцов.

class CJobs
{
public:
    enum {
        sizeOfDescription = 51
    };

    short nID;
    char szDescription[ sizeOfDescription ];
    short nMinLvl;
    short nMaxLvl;

    DWORD dwID;
    DWORD dwDescription;
    DWORD dwMinLvl;
    DWORD dwMaxLvl;

BEGIN_ACCESSOR_MAP(CJobs, 2)
    // Accessor 0 is the automatic accessor
    BEGIN_ACCESSOR(0, true)
        COLUMN_ENTRY_STATUS(1, nID, dwID)
    END_ACCESSOR()
    // Accessor 1 is the non-automatic accessor
    BEGIN_ACCESSOR(1, true)
        COLUMN_ENTRY_STATUS(2, szDescription, dwDescription)
        COLUMN_ENTRY_STATUS(3, nMinLvl, dwMinLvl)
        COLUMN_ENTRY_STATUS(4, nMaxLvl, dwMaxLvl)
    END_ACCESSOR()
END_ACCESSOR_MAP()
};

Основные объекты кода выглядят следующим образом. При вызове метода MoveNext выполняется автоматическое извлечение данных из идентификатора столбца первичного ключа с помощью метода 0. Обратите внимание, что метод Insert на завершающем этапе использует метод доступа 1 во избежание записи в столбец первичного ключа.

int main(int argc, char* argv[])
{
    // Initalize COM
    ::CoInitialize(NULL);

    // Create instances of the data source and session
    CDataSource source;
    CSession session;
    HRESULT hr = S_OK;

    // Set initialization properties
    CDBPropSet dbinit(DBPROPSET_DBINIT);
    dbinit.AddProperty(DBPROP_AUTH_USERID, OLESTR("my_user_id"));
    dbinit.AddProperty(DBPROP_INIT_CATALOG, OLESTR("pubs"));
    dbinit.AddProperty(DBPROP_INIT_DATASOURCE, OLESTR("(local)"));

    hr = source.Open("SQLOLEDB.1", &dbinit);
    if (hr == S_OK)
    {
        hr = session.Open(source);
        if (hr == S_OK)
        {
            // Ready to fetch/access data
            CTable<CAccessor<CJobs> > jobs;

            // Set properties for making the rowset a read/write cursor
            CDBPropSet dbRowset(DBPROPSET_ROWSET);
            dbRowset.AddProperty(DBPROP_CANFETCHBACKWARDS, true);
            dbRowset.AddProperty(DBPROP_CANSCROLLBACKWARDS, true);
            dbRowset.AddProperty(DBPROP_IRowsetChange, true);
            dbRowset.AddProperty(DBPROP_UPDATABILITY,
                DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE |
                DBPROPVAL_UP_DELETE);
   
            hr = jobs.Open(session, "jobs", &dbRowset);
            if (hr == S_OK)
            {
                // Calling MoveNext automatically retrieves ID
                // (using accessor 0)
                while(jobs.MoveNext() == S_OK)
                   printf_s("Description = %s\n", jobs.szDescription);

                hr = jobs.MoveFirst();
                if (hr == S_OK)
                {
                    jobs.nID = 25;
                    strcpy_s(&jobs.szDescription[0],
                             jobs.sizeOfDescription,
                             "Developer");
                    jobs.nMinLvl = 10;
                    jobs.nMaxLvl = 20;

                    jobs.dwDescription = DBSTATUS_S_OK;
                    jobs.dwID = DBSTATUS_S_OK;
                    jobs.dwMaxLvl = DBSTATUS_S_OK;
                    jobs.dwMinLvl = DBSTATUS_S_OK;

                    // Insert method uses accessor 1
                    // (to avoid writing to the primary key column)
                    hr = jobs.Insert(1);   
                }
                jobs.Close();
            }
            session.Close();
        }
        source.Close();
    }

    // Uninitialize COM
    ::CoUninitialize();
    return 0;
}

См. также

Основные понятия

Использование методов доступа

Записи пользователя