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


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

Существует три основных сценария, в которых необходимо использовать несколько методов доступа:

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

    • Accessor 0 содержит все столбцы.

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

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

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

    • Accessor 0 — это автоматический метод доступа; он извлекает все столбцы, кроме одного с большими данными.

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

    Используйте автоматический аргумент, чтобы указать, является ли метод доступа автоматическим.

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

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

  • В автоматическом методе доступа перемещайте такие методы, как MoveFirst, MoveLastMoveNextи MovePrev извлеките данные для всех указанных столбцов автоматически. Метод доступа 0 должен быть автоматическим методом доступа.

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

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

Класс записей пользователя выглядит следующим образом. Он настраивает два метода доступа: метод доступа 0 содержит только столбец первичного ключа (идентификатор) и метод доступа 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 метод ближе к концу использует метод accessor 1, чтобы избежать записи в столбец первичного ключа.

int main(int argc, char* argv[])
{
    // Initialize 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;
}

См. также

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