Partager via


Utilisation de plusieurs accesseurs dans un jeu de lignes

Il existe trois scénarios de base dans lesquels vous devez utiliser plusieurs accesseurs :

  • Plusieurs ensembles de lignes en lecture/écriture. Dans ce scénario, vous disposez d’une table avec une clé primaire. Vous souhaitez pouvoir lire toutes les colonnes de la ligne, y compris la clé primaire. Vous souhaitez également pouvoir écrire des données dans toutes les colonnes, à l’exception de la clé primaire (car vous ne pouvez pas écrire dans la colonne de clé primaire). Dans ce cas, vous configurez deux accesseurs :

    • Accesseur 0 contient toutes les colonnes.

    • Accesseur 1 contient toutes les colonnes à l’exception de la clé primaire.

  • Les performances. Dans ce scénario, une ou plusieurs colonnes ont une grande quantité de données, par exemple, des graphiques, du son ou des fichiers vidéo. Chaque fois que vous passez à une ligne, vous ne souhaitez probablement pas récupérer la colonne avec le fichier de données volumineux, car cela ralentit les performances de votre application.

    Vous pouvez configurer des accesseurs distincts dans lesquels le premier accesseur contient toutes les colonnes à l’exception de celles avec des données volumineuses et récupère automatiquement les données de ces colonnes ; le premier accesseur est l’accesseur automatique. Le deuxième accesseur récupère uniquement la colonne contenant des données volumineuses, mais elle ne récupère pas automatiquement les données de cette colonne. Vous pouvez mettre à jour d’autres méthodes ou extraire les données volumineuses à la demande.

    • Accesseur 0 est un accesseur automatique ; il récupère toutes les colonnes à l’exception de celle avec des données volumineuses.

    • Accesseur 1 n’est pas un accesseur automatique ; il récupère la colonne avec des données volumineuses.

    Utilisez l’argument automatique pour spécifier si l’accesseur est un accesseur automatique.

  • Plusieurs colonnes ISequentialStream. Dans ce scénario, vous avez plusieurs colonnes contenant des ISequentialStream données. Toutefois, chaque accesseur est limité à un ISequentialStream seul flux de données. Pour résoudre ce problème, configurez plusieurs accesseurs, chacun ayant un ISequentialStream pointeur.

Vous créez normalement des accesseurs à l’aide des macros BEGIN_ACCESSOR et END_ACCESSOR . Vous pouvez également utiliser l’attribut db_accessor . (Les accesseurs sont décrits plus loin dans Enregistrements utilisateur.) Les macros ou l’attribut spécifient si un accesseur est un accesseur automatique ou non automatique :

  • Dans un accesseur automatique, déplacez automatiquement des méthodes telles que MoveFirst, MoveLast, MoveNextet MovePrev récupérez automatiquement des données pour toutes les colonnes spécifiées. Accesseur 0 doit être l’accesseur automatique.

  • Dans un accesseur non automatique, la récupération ne se produit pas tant que vous n’appelez pas explicitement une méthode telle que Update, , InsertFetchou Delete. Dans les scénarios décrits ci-dessus, vous ne souhaiterez peut-être pas récupérer toutes les colonnes sur chaque déplacement. Vous pouvez placer une ou plusieurs colonnes dans un accesseur distinct et faire en sorte qu’un accesseur non automatique, comme indiqué ci-dessous.

L’exemple suivant utilise plusieurs accesseurs pour lire et écrire dans la table des travaux de la base de données pubs SQL Server à l’aide de plusieurs accesseurs. Cet exemple est l’utilisation la plus courante de plusieurs accesseurs ; consultez le scénario « plusieurs ensembles de lignes en lecture/écriture » ci-dessus.

La classe d’enregistrement utilisateur est la suivante. Il configure deux accesseurs : accesseur 0 contient uniquement la colonne de clé primaire (ID) et l’accesseur 1 contient d’autres colonnes.

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

Le code principal est le suivant. L’appel MoveNext récupère automatiquement les données à partir de l’ID de colonne de clé primaire à l’aide de l’accesseur 0. Notez comment la Insert méthode près de la fin utilise l’accesseur 1 pour éviter d’écrire dans la colonne de clé primaire.

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

Voir aussi

Utilisation des accesseurs
Enregistrements utilisateur