次の方法で共有


行セットでの複数アクセサーの使用

複数のアクセサーを使う必要がある場合は、3 つの基本的なシナリオがあります。

  • 複数の読み取り/書き込み行セット。 このシナリオでは、主キーを設定したテーブルがあります。 主キーを含め、行のすべての列を読み取る必要があります。 また、(主キー列に書き込めないので) 主キーを除くすべての列にデータを書き込む必要があります。 この場合、2 つのアクセサーを設定します。

    • アクセサー 0 にはすべての列が含まれています。

    • アクセサー 1 には主キーを除くすべての列が含まれています。

  • パフォーマンス。 このシナリオでは、1 つ以上の列に大量のデータ (グラフィック、サウンド、ビデオ ファイルなど) が格納されています。 行に移動するたびに大きなデータ ファイルを保持する列を取得すると、アプリケーションのパフォーマンスが低するため、避けたいところです。

    この場合、アクセサーを分けて設定することができます。1 つ目のアクセサーには、大きなデータを保持する列を除くすべての列を含め、これらの列から自動的にデータを取得するようにします。1 つ目のアクセサーは自動アクセサーです。 2 つ目のアクセサーでは、大きなデータを保持する列のみを取得します。ただし、この列からはデータを自動的に取得しません。 他の方法を使って、大きなデータをオンデマンドで更新またはフェッチすることもできます。

    • アクセサー 0 は自動アクセサーです。大きなデータを保持する列を除くすべての列を取得します。

    • アクセサー 1 は自動アクセサーではなく、大きなデータを保持する列を取得します。

    auto 引数を使って、自動アクセサーかどうかを指定します。

  • 複数の ISequentialStream 列。 このシナリオでは、ISequentialStream データを保持する列が複数あります。 ただし、各アクセサーは 1 つの ISequentialStream データ ストリームに制限されています。 この問題を解決するには、複数のアクセサーを設定し、それぞれが 1 つの ISequentialStream ポインターを設定します。

通常、アクセサーの作成には BEGIN_ACCESSOREND_ACCESSOR の各マクロを使います。 db_accessor 属性を使うこともできます (アクセサーの詳細については、 ユーザー レコード)。)マクロまたは属性は、アクセサーが自動アクセサーか非自動アクセサーかを指定します。

  • 自動アクセサーの場合、MoveFirstMoveLastMoveNextMovePrev などの move メソッドを使って、指定したすべての列のデータを自動的に取得します。 アクセサー 0 は自動アクセサーにするようにします。

  • 非自動アクセサーの場合、UpdateInsertFetchDelete などのメソッドを明示的に呼び出すまで、取得は行われません。 前述のシナリオでは、移動ごとにすべての列を取得したくない場合もあります。 次に示すように、1 つ以上の列を別のアクセサーに配置し、それを非自動アクセサーにすることができます。

次の例では、複数のアクセサーを使って、SQL Server pubs データベースの jobs テーブルの読み取りと書き込みを行っています。 この例は、複数のアクセサーの最も一般的な使用方法です。前述の「複数の読み取り/書き込み行セット」シナリオを参照してください。

ユーザー レコード クラスは次のとおりです。 2 つのアクセサーを設定します。アクセサー 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()
};

main コードは次のとおりです。 MoveNext を呼び出すと、アクセサー 0 を使って主キー列 ID からデータが自動的に取得されます。 末尾近くにある 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;
}

関連項目

アクセサーの使用
ユーザー レコード