在之前的博文“ArcEngine做一个“仿”ArcMap中的属性表”中,如果遇到数据量较大(万级以上)的数据就会出现查询很慢甚至内存溢出的问题,这对于一个实际应用的系统肯定是不允许的。好在ao中提供了定义过滤查询的接口:IQueryFilterDefinition3
在接口文档中对这个接口的说明是这样的:
Provides access to query filter definition properties.
定义过滤条件主要要用到IQueryFilterDefinition3接口中PostfixClause和PrefixClause属性,以及SetPaginationClause方法。其中SetPaginationClause方法提供了分页查询的功能(但是,Oracle数据库则不支持,会报“HRESULT:0x8004160A”错误,下文会说明),在定义了IQueryFilter之后插入下面的代码即可实现分页查询:
queryFilterDefinition3 = (IQueryFilterDefinition3)queryFilter;
queryFilterDefinition3.PrefixClause = "";
queryFilterDefinition3.PostfixClause = "order by " + OIDFieldName + " asc";
//查询第0-99行
queryFilterDefinition3.SetPaginationClause(0, 100);
实际上这个接口是对SQL语句进行了一次封装,个人猜想SetPaginationClause方法可能是传递SQL中limit关键字的参数,但是Oracle并不支持limit关键字,所以如果用IQueryFilterDefinition3接口定义Oracle数据库的查询条件时就会报“HRESULT:0x8004160A”,也就是数据库不支持错误。对于这种情况有两个解决思路:
***思路1:***把sde中的表当作普通表,用操作数据库的接口进行查询;
***思路2:***还是用ao的接口,通过控制读取的参数来实现,比如说,在遍历ICursor的时候加入一个变量,通过对变量值的判断来实现相应记录的读取,获取属性表的子表输出到UI。
这里我采用了第二种方法,第二种方法的主要的代码如下,第一种方法效率上可能更高,如果有用了第一种方法尝试的可以交流一下:
ICursor pCursor = pTable.Search(queryFilter, true);
IRow pRow = null;
int n = 0;
while ((pRow = pCursor.NextRow()) != null)
{
//lastrow和firstrow作为首行号和末行号参数
if ((firstRow != -1 && lastRow != -1) && n < firstRow)
{
++n;
continue;
}
if ((firstRow != -1 && lastRow != -1) && n > lastRow)
break;
//新建DataTable的行对象
pDataRow = pDataTable.NewRow();
for (int i = 0; i < pRow.Fields.FieldCount; i++)
{
if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeGeometry)
{
pDataRow["Shape"] = shapeType;
}
else if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeBlob)
{
pDataRow[i] = pRow.get_Value(i);// "Element";
}
else
{
string o = pRow.get_Value(i).ToString();
pDataRow[pRow.Fields.Field[i].Name] = pRow.get_Value(i);
}
}
pDataTable.Rows.Add(pDataRow);
pDataRow = null;
n++;
}