Windows Search 4.0をC#から利用する Part3

件数が多い場合の対処法について。Part2はこっち。
検索結果が数万件を超えるクエリを実行して、DataReaderで全件フェッチすると実行時間が10分とか20分とか平気でかかるみたいです。
任意の項目でソートもできますし、内容自体は1000件も出せれば運用上の問題はないとは思いますが、全体件数をなんとかして取得したいのでもう少し粘ってみました。

件数の取り方ですが、Windows Searchで使用するSQLの構文は、SQL ServerとかのT-SQLとは違うため、COUNT(*)とかは使えません。なのでMSDNにはOLE DBの行セットのプロパティを見ろと書いてました。Results Foundのところ。
http://msdn.microsoft.com/en-us/library/cc465173(VS.85).aspx

ただ、これはちょっとC#ではどうにも方法がわからなかったので、C++で全件数を取得するコードを書きました。この件数取得の部分だけC++/CLIのクラスライブラリにでも切り出しておけば、C#のコードから簡単に呼べると思います。

System::Int32^ DiggerData::DiggerDataSource::GetResultsFound(System::String^ sql)
{
    LONG ret = -1;//全件数の戻り値

    CDataSource cDataSource;
    PWSTR pszSQL = (PWSTR)(char*)(void*)System::Runtime::InteropServices::Marshal::StringToCoTaskMemUni(sql);;

    HRESULT hr = cDataSource.OpenFromInitializationString(L"provider=Search.CollatorDSO.1;EXTENDED PROPERTIES=\"Application=Windows\"");
    if (SUCCEEDED(hr))
    {
        CSession cSession;

        hr = cSession.Open(cDataSource);
        if (SUCCEEDED(hr))
        {
            CCommand<CDynamicAccessor, CRowset> cCommand;

            hr = cCommand.Open(cSession, pszSQL);
            if (SUCCEEDED(hr))
            {
                const ULONG cPropertyIDSets = 1;
                DBPROPIDSET	rgPropertyIDSets[cPropertyIDSets];
	            DBPROPSET *	rgPropSets		= NULL;//これに結果が入る
           		ULONG		cPropSets		= 0;

	            // プロパティ ID セットを設定する。
                DBPROPID	rgPropertyIDs[cPropertyIDSets];
	            rgPropertyIDs[0] = (DBPROPID)0x7;//Results Foundが入っているPROPID
	            rgPropertyIDSets[0].rgPropertyIDs = rgPropertyIDs;
	            rgPropertyIDSets[0].cPropertyIDs = 1;
                //Windows SearchのRowset PropertiesのPropertySetID
                const GUID guid = {0xAA6EE6B0, 0xE828, 0x11D0, {0xB2, 0x3E, 0x00, 0xAA, 0x00, 0x47, 0xFC, 0x01}};
                rgPropertyIDSets[0].guidPropertySet = guid;
    
                //IRowsetInfoからResults FoundのDBPROPIDSETを取得
                CComPtr<IRowsetInfo> spParent;
                hr = cCommand.m_spRowset->QueryInterface(&spParent);
                if (SUCCEEDED(hr))
                {
                    hr = ((IRowsetInfo *)spParent)->GetProperties(cPropertyIDSets, rgPropertyIDSets, &cPropSets, &rgPropSets);
                    if (SUCCEEDED(hr))
                    {
                        //DBPROPIDSETから件数を取得
                        ret = (*(*rgPropSets).rgProperties).vValue.lVal;
                    }   
                }
                cCommand.Close();
            } 
            cCommand.ReleaseCommand();
        }
    }

    return ret;
}


Windows Search関連はひとまずこれで終わりです。