基於C#的ArcEngine二次開發32:屬性sql查詢語句與IMap,ILayer,IFeatureLayer,IFeatureClass關係

1 ArcGIS中定義查詢和屬性查詢

1.1 SQL語句

以SQL模糊查詢LIKE運算符對應的通配符爲例

通配符查詢

通配符 描述 示例
% 包含零個或更多字符的任意字符串。 WHERE title LIKE '%computer%' 將查找處於書名任意位置的包含單詞 computer 的所有書名。
_(下劃線) 任何單個字符。 WHERE au_fname LIKE '_ean' 將查找以 ean 結尾的所有 4 個字母的名字(Dean、Sean 等)。
[ ] 指定範圍 ([a-f]) 或集合 ([abcdef]) 中的任何單個字符。 WHERE au_lname LIKE '[C-P]arsen' 將查找以arsen 結尾且以介於 C 與 P 之間的任何單個字符開始的作者姓氏,例如,Carsen、Larsen、Karsen 等。
[^] 不屬於指定範圍 ([a-f]) 或集合 ([abcdef]) 的任何單個字符。 WHERE au_lname LIKE 'de[^l]%' 將查找以 de 開始且其後的字母不爲 l 的所有作者的姓氏。

從圖層中選擇要素的代碼:

///<summary>Select features in the IActiveView by an attribute query using a SQL syntax in a where clause.</summary>
/// 
///<param name="activeView">An IActiveView interface</param>
///<param name="featureLayer">An IFeatureLayer interface to select upon</param>
///<param name="whereClause">A System.String that is the SQL where clause syntax to select features. Example: "CityName = 'Redlands'"</param>
///  
///<remarks>Providing and empty string "" will return all records.</remarks>
public void SelectMapFeaturesByAttributeQuery(ESRI.ArcGIS.Carto.IActiveView activeView, ESRI.ArcGIS.Carto.IFeatureLayer featureLayer, System.String whereClause)
{
      if(activeView == null || featureLayer == null || whereClause == null)
      {
        return;
      }
      ESRI.ArcGIS.Carto.IFeatureSelection featureSelection = featureLayer as ESRI.ArcGIS.Carto.IFeatureSelection; // Dynamic Cast

      // Set up the query
      ESRI.ArcGIS.Geodatabase.IQueryFilter queryFilter = new ESRI.ArcGIS.Geodatabase.QueryFilterClass();
      queryFilter.WhereClause = whereClause;

      // Invalidate only the selection cache. Flag the original selection
      activeView.PartialRefresh(ESRI.ArcGIS.Carto.esriViewDrawPhase.esriViewGeoSelection, null, null);

      // Perform the selection
      featureSelection.SelectFeatures(queryFilter, ESRI.ArcGIS.Carto.esriSelectionResultEnum.esriSelectionResultNew, false);

      // Flag the new selection
      activeView.PartialRefresh(ESRI.ArcGIS.Carto.esriViewDrawPhase.esriViewGeoSelection, null, null);
}

whereas語句的寫法:

//查詢與某一指定字符串一致的記錄
//直接寫
WhereClause = "RN = Y003";
//使用參數變量傳遞
string fieldStr = "Y003";
WhereClause = "RN = '" + fieldStr + "'";//注意單引號不要忘

//查詢以固定字符串開頭的記錄
//LXBM = "Y003456789"
//RN = "Y003"
WhereClause = "LXBM like 'Y003%'"
WhereClause = "LXBM like '" + RN+ "'%'";//注意單引號

//不等於
WhereClause = "LXBM != 10011";
WhereClause = "LXBM <> 10011";

//查詢多個要素
WhereClause = "NAME IS NOT NULL AND NAME <> '高架'"
語句 含義
FEAID IS NOT NULL 查詢FEAID不爲空的要素記錄
NAME <> '高架' 查詢NAME不爲高架的記錄,結果中不包含爲null的項

1.2 查詢不重複的要素

1.2.1 從GDB獲取不重複要素

//使用FeatureClass對象的IDataset接口來獲取dataset和workspace的信息
IDataset dataset = (IDataset)currentFeatureLayer.FeatureClass;
//使用IQueryDef接口的對象來定義和查詢屬性信息。通過IWorkspace接口的CreateQueryDef()方法創建該對象。
IQueryDef queryDef = ((IFeatureWorkspace)dataset.Workspace).CreateQueryDef();
//設置所需查詢的表格名稱爲dataset的名稱
queryDef.Tables = dataset.Name;
//設置查詢的字段名稱。可以聯合使用SQL語言的關鍵字,如查詢唯一值可以使用DISTINCT關鍵字。
queryDef.SubFields = currentFieldName ;
//執行查詢並返回ICursor接口的對象來訪問整個結果的集合
ICursor cursor = queryDef.Evaluate();
//使用IField接口獲取當前所需要使用的字段的信息
IFields fields = currentFeatureLayer.FeatureClass.Fields;
IField field = fields.get_Field(fields.FindField(currentFieldName));

//對整個結果集合進行遍歷,從而添加所有的唯一值
//使用IRow接口來操作結果集合。首先定位到第一個查詢結果。
IRow row = cursor.NextRow();
//如果查詢結果非空,則一直進行添加操作
while (row != null)
{
    //對String類型的字段,唯一值的前後添加'和',以符合SQL語句的要求
    if (field.Type == esriFieldType.esriFieldTypeString)
    {
        listBoxValues.Items.Add("\'" + row.get_Value(0).ToString() + "\'");
    }
    else
    {
        listBoxValues.Items.Add(row.get_Value(0).ToString());
    }
    //繼續執行下一個結果的添加
    row = cursor.NextRow();
}

1.2.2 從GDB/SHP獲取不重複要素

//獲取要素圖層的源
IFeatureClass feclass = currentFeatureLayer.FeatureClass;
//根據源數據創建遊標
IFeatureCursor cusro = feclass.Search(null, true);
IFeature fea = cusro.NextFeature();
//獲取源數據的所有字段
IFields fields = currentFeatureLayer.FeatureClass.Fields;
//獲取所選字段的Index
int index = fields.FindField(currentFieldName);

while (fea != null)
{
    string str;
    str = fea.get_Value(index).ToString();
    //如果值列表中還沒有str這個值
    if (!listBoxValues.Items.Contains("\'" + str + "\'"))
    {
        //將str加入到值列表,並且str前後加上單引號
        listBoxValues.Items.Add("\'" + str + "\'");
    }
    fea = cusro.NextFeature();
}
  • 2 IMap、ILayer、IFeatureLayer和IFeatureClass關係

剛開時學習 Engine 開發時,對於這幾個接口之間的關係總是理不清,因此寫下這篇文章做個總結

2.1 是什麼

在 engine 開發中,我覺得使用過程中應該將每個接口對應到 ArcMap 中的具體事物中,這才能對它們有深刻的認識,那麼,這幾個接口代表的事物是什麼呢?

  • IMap
    這相對來說比較好理解,Map就是許多圖層的集合,就像 ArcMap 中的 MXD文檔一樣,可以包括許多圖層 Layer.
  • ILayer
    Layer 是圖層對象,是數據的外殼,必須建立在數據的基礎上纔有意義。在 ArcMap 中,它可以表示任何圖層,例如要素圖層( IFeatureLayer ),柵格圖層( IRasterLayer ),圖形圖層集合( ICompositeGraphicsLayer )
  • IFeatureLayer
    繼承自ILayer,提供了訪問基於矢量數據圖層的屬性和方法,圖層的數據可以是Geodatabase、Shapefile或Coverage數據。如果使用FeatureLayer組件類,還可以通過IGeoFeatureLayer接口獲得更多的屬性和方法。提供了控制要素圖層的屬性和方法,例如標記屬性( AnnotationProperties )、註記顯示設置( DisplayAnnotation )
  • IFeatureClass
    獲取和設置要素類屬性的主要接口。如獲取要素類的類型,得到滿足某個查詢條件的要素個數,或在要素類中創建一個新的功能。

2.2 關係

其中IMap是由多個ILayer構成的,而IFeatureLayer是ILayer的一個子類,IFeatureClass是IFeatureLayer的一個屬性。

2.2.1 從IMap中獲取IFeatureLayer

        /// <summary>
        /// 根據圖層名找到圖層 
        /// </summary>
        /// <param name="pMap">地圖名稱</param>
        /// <param name="layerName">圖層名稱</param>
        /// <returns>未找到圖層返回null,找到圖層返回目標圖層</returns>
        public static IFeatureLayer GetLayerByName(IMap pMap, string layerName)
        {
            for(int i = 0; i < pMap.LayerCount; i++)
            {
                if(pMap.getLayer(i).Name == layerName)
                {
                    return pMap.getLayer(i) as IFeatureLayer;
                }
            }
            return null;
        }

2.2.2 從IMap中獲取IFeatureClass

注意:使用此函數時,不能再通過接口跳轉到IFeatureLayer

        /// <summary>
        /// 根據圖層名找到圖層 
        /// </summary>
        /// <param name="pMap">地圖名稱</param>
        /// <param name="layerName">圖層名稱</param>
        /// <returns>未找到圖層返回null,找到圖層返回目標圖層</returns>
        public static IFeatureClass GetLayer(IMap pMap, string layerName)
        {
            for(int i = 0; i < pMap.LayerCount; i++)
            {
                if(pMap.getLayer(i).Name == layerName)
                {
                    return (pMap.getLayer(i) as IFeatureLayer).FeatureClass;
                }
            }
            return null;
        }

2.3 向圖層中添加字段

public void addFieldIntoFeatureClass(IFeatureClass feaClass, string fieldName)
{
    int fieldIndex = feaClass.FinfField(fieldName);
    if(fieldIndex != -1)
    {
        IField pField = new FieldClass();
        IFieldEdit pFieldEdit = (IFieldEdit)pField;
        pFieldEdit.Name_2 = fieldName;
        pFieldEdit.Type_2 = esriFieldType.esriFieldTypeString;
        pFieldEdit.Length_2 = 100;
        pFieldsEdit.AddField(pField);
    }
}

2.4 獲取IMap下某圖層所屬的數據庫名稱

IFeatureLayer pFeaLayer = getLayerByName(pMap, "LRDL");
string gdbName = pFeaLayer.FeatureClass.FeatureDataset.Workspace.PathName;

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章