共用方式為


在資料列集上使用多重存取子

有三個基本案例,您需要使用多個存取子:

  • 多個讀取/寫入數據列集。 在此案例中,您有具有主鍵的數據表。 您想要能夠讀取資料列中的所有資料行,包括主鍵。 您也想要將數據寫入主鍵以外的所有資料列(因為您無法寫入主鍵數據行)。 在此情況下,您會設定兩個存取子:

    • 存取子 0 包含所有資料行。

    • 存取子 1 包含主鍵以外的所有數據行。

  • 效能: 在此案例中,一或多個數據行具有大量數據,例如圖形、音效或視訊檔案。 每次移至資料列時,您可能不想使用大型資料檔擷取數據行,因為這樣做會降低應用程式的效能。

    您可以設定個別的存取子,其中第一個存取子包含除具有大型數據的數據以外的所有數據行,而且會自動從這些數據行擷取數據;第一個存取子是 auto 存取子。 第二個存取子只會擷取保存大型數據的數據行,但不會自動從這個數據行擷取數據。 您可以讓其他方法視需要更新或擷取大型數據。

    • 存取子 0 是自動存取子;它會擷取除了具有大型數據的數據行以外的所有數據行。

    • 存取子 1 不是自動存取子;它會擷取具有大型數據的數據行。

    使用 auto 自變數來指定存取子是否為自動存取子。

  • 多個 ISequentialStream 數據行。 在此案例中,您有超過一個數據行持有 ISequentialStream 數據。 不過,每個存取子限制為一個 ISequentialStream 數據流。 若要解決此問題,請設定數個存取子,每個存取子都有一個 ISequentialStream 指標。

您通常會使用 BEGIN_ACCESSOREND_ACCESSOR 巨集來建立存取子。 您也可以使用 db_accessor 屬性。 (存取子會在 中 進一步說明使用者記錄。)巨集或屬性會指定存取子是自動存取子或非自動存取子:

  • 在自動存取子中,移動方法,例如 MoveFirstMoveLastMoveNextMovePrev 自動擷取所有指定數據行的數據。 存取子 0 應該是自動存取子。

  • 在非自動存取子中,除非您明確呼叫 、、 FetchDeleteUpdateInsert方法,否則不會發生擷取。 在上述案例中,您可能不想在每次移動時擷取所有數據行。 您可以將一或多個數據行放在不同的存取子中,並使該數據行成為非自動存取子,如下所示。

下列範例使用多個存取子,使用多個存取子讀取和寫入 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()
};

主要程序代碼如下所示。 使用存取子 0,呼叫 MoveNext 會自動從主鍵數據行標識符擷取數據。 請注意結尾附近的 方法如何使用 Insert 存取子 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;
}

另請參閱

使用存取子
使用者資料錄