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


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

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

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

    • В методе доступа 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;
}

См. также

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

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

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