Verwenden mehrerer Zugriffsmethoden für ein Rowset

Es gibt drei grundlegende Szenarien, in denen Sie mehrere Accessoren verwenden müssen:

  • Mehrere Zeilensätze mit Lese-/Schreibzugriff. In diesem Szenario haben Sie eine Tabelle mit einem Primärschlüssel. Sie möchten alle Spalten in der Zeile lesen können, einschließlich des Primärschlüssels. Sie möchten auch Daten in alle Spalten mit Ausnahme des Primärschlüssels schreiben können (da Sie nicht in die Primärschlüsselspalte schreiben können). In diesem Fall richten Sie zwei Accessoren ein:

    • Accessor 0 enthält alle Spalten.

    • Accessor 1 enthält alle Spalten mit Ausnahme des Primärschlüssels.

  • Leistung. In diesem Szenario weist eine oder mehrere Spalten eine große Datenmenge auf, z. B. Grafiken, Sound oder Videodateien. Jedes Mal, wenn Sie zu einer Zeile wechseln, möchten Sie die Spalte mit der großen Datendatei wahrscheinlich nicht abrufen, da dies die Leistung Ihrer Anwendung verlangsamen würde.

    Sie können separate Accessoren einrichten, in denen der erste Accessor alle Spalten außer dem mit großen Daten enthält, und daten automatisch aus diesen Spalten abruft. Der erste Accessor ist der automatische Accessor. Der zweite Accessor ruft nur die Spalte ab, die große Daten enthält, aber es werden keine Daten automatisch aus dieser Spalte abgerufen. Sie können andere Methoden aktualisieren oder die großen Daten bei Bedarf abrufen.

    • Accessor 0 ist ein automatischer Accessor; sie ruft alle Spalten mit Ausnahme der Spalten mit großen Daten ab.

    • Accessor 1 ist kein automatischer Accessor; sie ruft die Spalte mit großen Daten ab.

    Verwenden Sie das auto-Argument, um anzugeben, ob der Accessor ein automatischer Accessor ist.

  • Mehrere ISequentialStream-Spalten. In diesem Szenario haben Sie mehr als eine Spalte mit ISequentialStream Daten. Jeder Accessor ist jedoch auf einen ISequentialStream Datenstrom beschränkt. Um dieses Problem zu lösen, richten Sie mehrere Accessoren ein, die jeweils einen ISequentialStream Zeiger haben.

Normalerweise erstellen Sie Accessoren mithilfe der BEGIN_ACCESSOR und END_ACCESSOR Makros. Sie können auch das attribut db_accessor verwenden. (Accessoren werden weiter in Benutzerdatensätze.) Die Makros oder das Attribut geben an, ob ein Accessor ein automatischer oder nicht automatischer Accessor ist:

  • Verschieben Sie in einem automatischen Accessor Methoden wie MoveFirst, MoveLast, MoveNextund MovePrev rufen Sie Daten für alle angegebenen Spalten automatisch ab. Accessor 0 sollte der automatische Accessor sein.

  • In einem nicht automatischen Accessor tritt der Abruf erst auf, wenn Sie eine Methode wie Update, , Insert, Fetchoder Delete. In den oben beschriebenen Szenarien möchten Sie möglicherweise nicht alle Spalten auf jeder Verschiebung abrufen. Sie können eine oder mehrere Spalten in einem separaten Accessor platzieren und diesen als nicht automatischen Accessor festlegen, wie unten dargestellt.

Im folgenden Beispiel werden mehrere Accessoren zum Lesen und Schreiben in die Auftragstabelle der SQL Server Pubs-Datenbank mit mehreren Accessoren verwendet. Dieses Beispiel ist die am häufigsten verwendete Verwendung mehrerer Accessoren; siehe oben das Szenario "Mehrere Zeilensätze mit Lese-/Schreibzugriff".

Die Benutzerdatensatzklasse lautet wie folgt. Es richtet zwei Accessoren ein: Accessor 0 enthält nur die Primärschlüsselspalte (ID) und Accessor 1 enthält weitere Spalten.

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

Der Hauptcode lautet wie folgt. Durch aufrufen MoveNext werden automatisch Daten aus der Primärschlüsselspalten-ID mithilfe des Accessors 0 abgerufen. Beachten Sie, wie die Insert Methode am Ende Accessor 1 verwendet, um das Schreiben in die Primärschlüsselspalte zu vermeiden.

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

Siehe auch

Verwenden von Zugriffsmethoden
Benutzerdatensätze