Compartilhar via


Usando vários acessadores em um conjunto de linhas

Há três cenários básicos de que você precisa usar vários acessadores:

  • Multiple read/write rowsets. Neste cenário, você tem uma tabela com uma chave primária. Você deseja ser capaz de ler todas as colunas na linha, incluindo a chave primária. Você também deseja poder gravar dados em todas as colunas exceto a chave primária (porque você não pode gravar na coluna de chave primária). Nesse caso, configure dois acessadores:

    • O acessador 0 contém todas as colunas.

    • O acessador 1 contém todas as colunas exceto a chave primária.

  • Desempenho. Neste cenário, uma ou mais colunas contêm uma grande quantidade de dados, por exemplo, gráficos, de correta, ou arquivos de exibição. Cada vez que você se move para uma linha, você provavelmente não deseja recuperar a coluna com o arquivo de dados grande, pois isso retardaria o desempenho de seu aplicativo.

    Você pode configurar os acessadores separados em que o primeiro acessador contém todas as colunas exceto aquela com dados grandes, e recupera dados dessas colunas automaticamente; este é o acessador automático. O segundo acessador recupera apenas a coluna que contém dados grandes, mas não recupera dados dessa coluna automaticamente. Você pode ter outra atualização dos métodos ou buscar dados grandes sob demanda.

    • O acessador 0 é um acessador automático; recupera todas as colunas exceto aquela com dados grandes.

    • O acessador 1 não é um acessador automático; recupera a coluna com dados grandes.

    Use o argumento automático para especificar se o acessador é um acessador automático.

  • Multiple ISequentialStream columns. Neste cenário, você tem mais de uma coluna que contém dados de ISequentialStream . No entanto, cada acessador é limitado a um fluxo de dados de ISequentialStream . Para resolver esse problema, configure vários acessadores, cada um ponteiro de ISequentialStream contentor.

Você geralmente cria os acessadores que usam macros de BEGIN_ACCESSOR e de END_ACCESSOR . Você também pode usar o atributo de db_accessor . (Os acessadores são descritos mais em Registros de usuário.) Macros ou o atributo especifica se um acessador é um acessador automático ou do não automático:

  • Em um acessador automático, os métodos de movimentação como MoveFirst, MoveLast, MoveNext, e MovePrev recuperam dados para todas as colunas especificadas automaticamente. O acessador 0 deve ser o acessador automático.

  • Em um acessador de não automático, a recuperação não ocorre até que você chame explicitamente um método como Atualizar, Inserir, Buscar, ou Excluir. Em cenários descritos anteriormente, você não queira recuperar todas as colunas em cada movimentação. Você pode colocar uma ou mais colunas em um acessador separado e fazer esse acessador de um não automático, como mostrado abaixo.

O exemplo a seguir usa vários acessadores para ler e gravar na tabela de trabalho da base de dados pubs do SQL Server usando vários acessadores. Este é o uso mais comum de vários acessadores; consulte “cenário de vários conjuntos de linhas de leitura/gravação” acima.

A classe de registro de usuário é como segue. Configura de dois acessadores: o acessador 0 contém apenas a coluna de chave primária (ID) e o acessador 1 contém outras colunas.

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()
};

O código principal é como segue. A chamada MoveNext recupera dados automaticamente a ID da coluna de chave primária usando o acessador 0. Observe como o método de Inserir do acessador 1 dos usos finais evitar gravar na coluna de chave primária.

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;
}

Consulte também

Conceitos

Usando acessadores

Registros de usuário