查询geodatabase对象的三种常见的接口是IQueryFilter、ISpatialFilter、IQueryDef接口。每个接口都有不同的功能,如下表所示:
Requirement | IQueryFilter | ISpatialFilter | IQueryDef |
---|---|---|---|
Apply attribute constraints(支持属性约束) | True | True | True |
Apply spatial constraints (支持空间约束) | False | True | False |
Query results contain fields from multiple tables (查询结果包含多个表的字段,可理解为支持多表连接查询) | False | False | True |
Query results returned as a cursor (查询结果返回一个游标对象) | True | True | True |
RecordSet objects can be created from results (从结果可以创建记录集对象) | True | True | True |
Returned records can be edited (查询结果可以被编辑) | True | True | False |
Records include edits made in active edit session | True | True | False |
// 创建过滤器对象
IQueryFilter queryFilter = new QueryFilterClass();
// 设置查询字段
queryFilter.SubFields = "NAME, ADDRESS";
// 设置查询条件
queryFilter.WhereClause = "TYPE = 'Restaurant'";
// 接口跳转到IQueryFilterDefinition接口,利用它的PostfixClause属性来对某个字段排序
IQueryFilterDefinition queryFilterDef = (IQueryFilterDefinition)queryFilter;
queryFilterDef.PostfixClause = "ORDER BY NAME";
// 读取查询结果
int nameIndex = table.FindField("NAME");
int addressIndex = table.FindField("ADDRESS");
//用ComReleasr对象管理Com对象的生命周期,保证Com对象的释放
Using(ComReleaser comReleaser = new ComReleaser())
{
ICursor cursor = table.Search(queryFilter, true);
comReleaser.ManageLifetime(cursor);
IRow row = null;
while ((row = cursor.NextRow()) != null)
{
String name = Convert.ToString(row.get_Value(nameIndex));
String address = Convert.ToString(row.get_Value(addressIndex));
Console.WriteLine("{0} - {1}", name, address);
//这块强烈建议row释放掉,如果做大数据操作的时候这块不释放 内存会撑爆的。
System.Runtime.InteropServices.Marshal.ReleaseComObject(row);
}
}
相关接口同IQueryFilter
// 创建一个查询范围
IEnvelope envelope = new EnvelopeClass();
envelope.PutCoords( - 84.4078, 33.7787, - 84.3856, 33.7997);
// 创建一个空间过滤器,并设置其相关的属性
ISpatialFilter spatialFilter = new SpatialFilterClass
{
Geometry = envelope, //空间过滤条件
GeometryField = featureClass.ShapeFieldName, //空间字段名称
SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects //空间关系
};
// Set the attribute constraints and subfields.
// 设置属性过滤条件
spatialFilter.WhereClause = "NAME <> 'Ramp' AND PRE_TYPE NOT IN ('Hwy', 'I')";
// 设置属性查询的字段
spatialFilter.SubFields = "NAME, TYPE";
// 获取查询字段的索引
int nameIndex = featureClass.FindField("NAME");
int typeIndex = featureClass.FindField("TYPE");
//使用ComReleser管理Com对象
using(ComReleaser comReleaser = new ComReleaser())
{
//读取查询结果
IFeatureCursor featureCursor = featureClass.Search(spatialFilter, true);
comReleaser.ManageLifetime(featureCursor);
IFeature feature = null;
while ((feature = featureCursor.NextFeature()) != null)
{
String roadName = Convert.ToString(feature.get_Value(nameIndex));
String roadType = Convert.ToString(feature.get_Value(typeIndex));
Console.WriteLine("Name: {0}, Type: {1}", roadName, roadType);
//这块强烈建议feature释放掉,如果做大数据操作的时候这块不释放 内存会撑爆的。
System.Runtime.InteropServices.Marshal.ReleaseComObject(feature);
}
}
If a geometry bag is being used as the filter’s query geometry, create a spatial index for the geometry bag before being assigned to the geometry property. This can drastically increase the query’s efficiency. The following code example shows how to do this:
如果使用几何包对象作为过滤的几何图形,在为ISpatialFilter对象设置Geometry属性之前,先对几何包对象创建空间索引,这样能大大提高查询的效率,下面是创建空间索引的示例代码:
// 将几何包对象转换到ISpatialIndex对象上去
ISpatialIndex spatialIndex = (ISpatialIndex)geometryBag;
spatialIndex.AllowIndexing = true;
spatialIndex.Invalidate();
IQueryDef对象可由IFeatureWorkspace.CreateQueryDef 方法创建
注意事项:
1)只能在ArcSDE、PGDB、FGDB数据源上使用(注意:shp数据不支持),数据集的历史表示 不被QueryDef游标支持(翻译可能不太准确,详见官方文档)。
2)支持多表查询,但是查询的结果不能进行修改!
3)使用IQueryDef查询出来的游标,用此游标获取的字段的别名和字段名一致(如果是要获取字段的中文别名,请使用其他方法获取游标)
IQueryName2
同创建游标一样,IQueryDef对象能用于生成一个虚拟的表或要素类。示例代码如下:
// Create a reference to a TableQueryName object.
IQueryName2 queryName2 = new TableQueryNameClass();
queryName2.PrimaryKey = String.Empty;
// Specify the query definition.
queryName2.QueryDef = queryDef;
// Get a name object for the workspace.
IDataset dataset = (IDataset)workspace;
IWorkspaceName workspaceName = (IWorkspaceName)dataset.FullName;
// Cast the TableQueryName object to the IDatasetName interface and open it.
IDatasetName datasetName = (IDatasetName)queryName2;
datasetName.WorkspaceName = workspaceName;
datasetName.Name = tableName;
IName name = (IName)datasetName;
// Open the name object and get a reference to a table object.
ITable table = (ITable)name.Open();
// 创建IQueryDef2对象
IQueryDef2 queryDef2 = (IQueryDef2)featureWorkspace.CreateQueryDef();
// 设置查询的表、字段及后缀查询条件
queryDef2.Tables = "Cities";
queryDef2.SubFields = "Name, Pop1996";
queryDef2.PostfixClause = "ORDER BY Pop1996 DESC";
// 执行查询
属性及方法详解(ComReleaser comReleaser = new ComReleaser())
{
ICursor cursor = queryDef2.Evaluate2(true);
comReleaser.ManageLifetime(cursor);
int nameIndex = cursor.FindField("Name");
int pop1996Index = cursor.FindField("Pop1996");
IRow row = null;
while ((row = cursor.NextRow()) != null)
{
String cityName = Convert.ToString(row.get_Value(nameIndex));
int population = Convert.ToInt32(row.get_Value(pop1996Index));
Console.WriteLine("{0}: {1}", cityName, population);
}
}
参考官方教材:传送门
使用ITableSort接口对有ObjectIDs的表(或要素类)进行排序。使用该接口进行排序,必须设置Fields属性和Table(或SelectionSet)属性。
可写 | Ascending | |
---|---|---|
可写 | CaseSensitive | CaseSensitive Character fields case sensitive. Default: False. |
可写 | Compare | Compare call back interface. Specify Null (default) for normal behavior. |
可写 | Cursor | The cursor of the data to sort on. Ensure that sorting fields are available. Cancels SelectionSet. |
可写 | Fields | Comma list of field names to sort on. |
可读 | IDByIndex | A id by its index value. |
可读 | IDs | IDs List of sorted IDs. |
可读可写 | QueryFilter | The query filter on table or selection set. |
可读 | Rows | Cursor of sorted rows. |
可读可写 | SelectionSet | The selection set as a source of the data to sort on. Cancels Cursor. |
方法 | Sort | Sort rows. |
可写 | SortCharacters | Number of characters to sort on, for string fields. A null (default) sorts on the whole string. |
可读可写 | Table | The table as a source of the data to sort on. |
- 示例代码
1.排序必须设置的属性
// 打开要素类"counties"
IFeatureClass featureClass = featureWorkspace.OpenFeatureClass("Counties");
ITable table = (ITable)featureClass;
// 创建一个ITableSort接口对象
ITableSort tableSort = new TableSortClass();
tableSort.Table = table;
// 如果标识连接数据后的结果,记得完整的引用字段
tableSort.Fields = "State_Name, Name"; // "Name"字段是Country name字段
示例代码
IQueryFilter queryFilter = new QueryFilterClass();
queryFilter.WhereClause = "POP > 10000";
tableSort.QueryFilter = queryFilter;
tableSort.set_Ascending("State_Name", false);
tableSort.set_Ascending("Name", true);
tableSort.set_CaseSensitive("State_Name", true);
tableSort.set_CaseSensitive("Name", true);
tableSort.Sort(null);// ITrackCancel,支持取消操作
// 获取排序后的游标对象
ICursor cursor = tableSort.Rows;
// 获取字段所以
int stateNameIndex = cursor.Fields.FindField("State_Name");
int countyNameIndex = cursor.Fields.FindField("Name");
int popIndex = cursor.Fields.FindField("POP");
// 遍历行 并取得相关的字段值
while ((row = cursor.NextRow()) != null)
{
Console.WriteLine("{0}, {1}, {2}", row.get_Value(stateNameIndex), row.get_Value
(countyNameIndex), row.get_Value(popIndex));
}
// Get an enumerator of ObjectIDs for the sorted rows.
IEnumIDs enumIDs = tableSort.IDs;
// Get field indexes for efficient reuse.
int stateNameIndex = table.FindField("State_Name");
int countyNameIndex = table.FindField("Name");
int popIndex = table.FindField("POP");
int id = - 1;
IRow row = null;
while ((id = enumIDs.Next()) != - 1)
// -1 is returned after the last valid ID is reached.
{
row = table.GetRow(id);
Console.WriteLine("{0} , {1} , {2}", row.get_Value(stateNameIndex),
row.get_Value(countyNameIndex), row.get_Value(popIndex));
}
自定义类实现ITableSortCallBack接口,实现自己的Compare方法即可进行自定义排序。
ITableSort tableSort = new TableSortClass();
tableSort.Compare = new StreetNumberSort();
tableSort.Table = table;
tableSort.Fields = "StreetNum";
public class StreetNumberSort: ITableSortCallBack
{
public int Compare(object value1, object value2, int fieldIndex, int fieldSortIndex)
{
// Seperate the numeric and non-numeric components of each value.
int value1Number = - 1;
int value2Number = - 1;
String value1Suffix = null;
String value2Suffix = null;
SeperateValues(value1.ToString(), out value1Number, out value1Suffix);
SeperateValues(value2.ToString(), out value2Number, out value2Suffix);
// Compare the numeric components of the street numbers.
if (value1Number != value2Number)
{
// If value1 is less than value2, return -1; otherwise, return 1.
if (value1Number < value2Number)
{
return - 1;
}
else
{
return 1;
}
}
// The numeric values are equal. Compare the suffixes.
int compareResult = String.Compare(value1Suffix, value2Suffix);
if (compareResult < 0)
{
return - 1;
}
else if (compareResult == 0)
{
return 0;
}
else
{
return 1;
}
}
private void SeperateValues(String streetNumber, out int number, out Strin suffix)
{
// Step through the street number to the end or until a null character is reached.
StringBuilder numberBuilder = new StringBuilder();
StringBuilder suffixBuilder = new StringBuilder();
for (int i = 0; i < streetNumber.Length && streetNumber[i] != '\0'; i++)
{ Char currentChar = streetNumber[i];
if (currentChar >= '0' && currentChar <= '9')
{
numberBuilder.Append(currentChar);
}
else
{
suffixBuilder.Append(currentChar);
}
}
// Set the outbound parameters.
Int32.TryParse(numberBuilder.ToString(), out number);
suffix = suffixBuilder.ToString();
}
}
两种连接数据,关联查询的方法:
- 使用IQueryDef接口进行关联查询
- 使用RelQueryTables 进行关联查询
示例代码:
这里写代码片
对数据进行插入、更新、删除时最好是开始事务编辑,这样当遇到异常时不会损坏数据,而且也可以进行回滚操作。
StartEditing (boolwithUndoRedo):开启编辑流程(恢复/取消恢复)
StartEditOperation:开始编辑操作
StopEditOperation:结束编辑操作,用来确保编辑操作的完成
StopEditing (boolsaveEdits):结束编辑流程(保存编辑结束编辑流程或不保存编辑结束编辑流程)
UndoEditOperation:用于编辑状态的回滚操作。
RedoEditOperation:用于编辑状态的恢复操作。
AbortEditOperation:取消所有的编辑操作。
数据插入有两种方式,一种通过游标进行插入,一种通过创建新行来插入。
using(ComReleaser comReleaser = new ComReleaser())
{
ICursor pCursor=pTable.Insert(true);
comReleaser.ManageLifetime(pCursor);
IRowBuffer pRowBuffer=pTable.CreateRowBuffer();
comReleaser.ManageLifetime(pRowBuffer);
//设置属性(此处代码略)
int iFieldIndex=pTable.FindField("FieldName");
pRowBuffer.set_Value(iFieldIndex,"FieldValue");
pCursor.InsertRow(pRowBuffer);
pCursor.Flush();
}
IRow pRow=pTable.CreateRow();
pRow.set_Value(iFldIndex,fieldValue);
pRow.Store();
大量插入数据的时候,用游标插入更快,可以每几千条Flush一次,而不是每插入一条就Flush一次。
数据更新有两种方式,一种通过游标进行更新,一种是直接更新。
游标更新
ICursor pCursor = pTable.Update(pQueryFilter, false);//建议使用False进行更新
pRow.set_Value(iFldIndex1,fieldValue1);
pRow.set_Value(iFldIndex2,fieldValue2);
pCursor.UpdateRow(pRow);
直接更新
pRow.set_Value(iFldIndex1,fieldValue1);
pRow.set_Value(iFldIndex2,fieldValue2);
pRow.Store();
在更新数据的时候,建议开始编辑模式,以防数据编辑失败,还有就是大量数据更新,建议用游标进行更新,效率会更高。
数据删除有好几种方式,1)通过执行SQL进行删除 2)通过更新游标删除 3)直接查询删除 4)直接删除查询的行
略
请参考:http://blog.sina.com.cn/s/blog_5e4c933d010116n5.html
删除的时候一定要注意开启编辑模式