I've used Index Server using MSIDXS(Microsoft® OLE DB Provider for Indexing Service ) to query LAN documents from ASP.NET, but on the big catalogs it is quite slow. In a few places it's noted, that MSIDXS is significally slower than IXSSO. So I decided to try IXSSO and found an article on ASP101.The article limits the number returned using Q.MaxRecords = 250 for performance reasons.
However if you want to show how many total records satisfied your search it's not a good idea to limit the number of returned records.
If I didn't specified MaxRecords, I found that using IXSSO with DataAdapter.Fill is not quicker than MSIDXS.
Further investigation showed that in the following two lines of code:
Dim rs As Object = Q.CreateRecordset("nonsequential")
da.Fill(ds, rs, sTableName)
to fill ADO.NET dataset takes 20 times more time than to CreateRecordset for my big catalog(rs.RecordCount=65000).
Because the application actually shows only one page per time, I wanted to use Fill overload to refreshes rows in a specified range but there is no public overload for ADO Recordset.
(Using Reflector I found that there are private methods in System.Data.OleDb namespace but unfortunately it isn't possible to use them externally)
It is essential to use "nonsequential" parameter of CreateRecordset, because it returns back valid rs.RecordCount.(As a test I've tried to pass "sequential", but then I had to to calculate total count of records manually, which is very slow.)
So I had to create function that copies to the DataTable only specified range(see the code below).
public static int Fill(DataSet ds,string TableName, ADODB.Recordset rs, int startRecord, int maxRecords)
{
DataTable table = new DataTable( TableName);
int fieldCount = BuildSchemaTable( table, rs);
table.BeginLoadData();
object[] values = new object[fieldCount];
int nCount=0;
while (0 < startRecord){
if (rs.EOF)
{
return nCount;
}
rs.MoveNext();
startRecord--;
nCount++;
}
int num1 = 0;
if (0 < maxRecords)
{
while ((num1 < maxRecords) && !rs.EOF)
{
RecordsetToArray(rs,values);
table.LoadDataRow(values, true);
rs.MoveNext();
num1++;
}
}
nCount+=num1;
table.EndLoadData();
ds.Tables.Add(table);
return nCount;
}
protected static int BuildSchemaTable(DataTable table, ADODB.Recordset rs)
{
int fieldCount = rs.Fields.Count;
for (int i = 0; i < fieldCount; i++)
{ table.Columns.Add(rs.Fields[i].Name , FromAdoDbType(rs.Fields[i].Type));
}
return fieldCount;
}
protected static void RecordsetToArray(ADODB.Recordset rs,object[] values)
{
Debug.Assert(values.Length>=rs.Fields.Count);
for (int i=0;i<rs.Fields.Count;i++)
{
values[i]=rs.Fields[i].Value;
}
}
public static System.Type FromAdoDbType(ADODB.DataTypeEnum AdoDbType)
{
switch (AdoDbType)
{
case ADODB.DataTypeEnum.adEmpty:
{
return null;
}
case ADODB.DataTypeEnum.adBoolean:
{
return typeof(Boolean);
}
case ADODB.DataTypeEnum.adTinyInt:
{
return typeof(SByte);
}
case ADODB.DataTypeEnum.adSingle:
{
return typeof(Single);
}
case ADODB.DataTypeEnum.adSmallInt:case ADODB.DataTypeEnum.adUnsignedTinyInt:{
return typeof(Int16);
}
case ADODB.DataTypeEnum.adInteger:case ADODB.DataTypeEnum.adUnsignedSmallInt:{
return typeof(Int32);
}
case ADODB.DataTypeEnum.adBigInt:case ADODB.DataTypeEnum.adUnsignedInt:{
return typeof(Int64);
}
case ADODB.DataTypeEnum.adCurrency:case ADODB.DataTypeEnum.adDecimal:case ADODB.DataTypeEnum.adNumeric:
case ADODB.DataTypeEnum.adUnsignedBigInt:{
return typeof(Decimal);
}
case ADODB.DataTypeEnum.adDate:case ADODB.DataTypeEnum.adDBDate:case ADODB.DataTypeEnum.adDBTime:
case ADODB.DataTypeEnum.adDBTimeStamp:case ADODB.DataTypeEnum.adFileTime:
{
return typeof(DateTime);
}
case ADODB.DataTypeEnum.adGUID:
{
return typeof(Guid);
}
case ADODB.DataTypeEnum.adError:
{
return typeof(System.Runtime.InteropServices.ExternalException);
}
case ADODB.DataTypeEnum.adIUnknown:case ADODB.DataTypeEnum.adIDispatch:case ADODB.DataTypeEnum.adVariant:
case ADODB.DataTypeEnum.adPropVariant:
{
return typeof(object);
}
case ADODB.DataTypeEnum.adChar:case ADODB.DataTypeEnum.adWChar:case ADODB.DataTypeEnum.adBSTR:
case ADODB.DataTypeEnum.adVarWChar:
{
return typeof(String);
}
}