FeatureClass获取多字段唯一记录

本文介绍了一种高效的GIS数据处理方法,对比了三种不同方式获取要素类字段唯一值的性能:常规方式、使用枚举及利用IQueryDef2接口。实验表明,在处理大量地理信息系统数据时,IQueryDef2接口在某些情况下提供了最优的性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     测试数据:20万记录的图层,30个字段

1、常规方式

   gdb:耗时2846ms  mdb:3293ms    shp:5769ms

/// <summary>
/// 得到要素类某字段的唯一值
/// </summary>
/// <param name="FClass">要素类</param>
/// <param name="strFld">指定要得到唯一值的字段</param>
public List<string> GetUniqueValue(IFeatureClass FClass,string strFld)
{
    List<string> plist = new List<string>();
    using (ComReleaser comReleaser = new ComReleaser())
    {
        int idx = FClass.FindField(strFld);
        var value = "";
        IFeatureCursor cursor = FClass.Search(null, true);
        comReleaser.ManageLifetime(cursor);
        IFeature feature = null;
        while ((feature = cursor.NextFeature()) != null)
        {
            value = feature.Value[idx].ToString();
            if (!plist.Contains(value))
                plist.Add(value);
        }
    }
    return plist;
}

在获取多字段唯一值时比IQueryDef2接口慢了许多:

        /// <summary>
        /// 获取要素类唯一值
        /// </summary>
        /// <param name="pFeatureClass">要素类</param>
        /// <param name="flds">字段集合</param>
        /// <param name="queryFilter">筛选条件</param>
        /// <returns></returns>
        public static List<Dictionary<string,object>> GetUniqueValue(IFeatureClass pFeatureClass, List<string> flds,IQueryFilter queryFilter, out int fcount)
        {
            fcount = 0;
            Dictionary<string, int> fldidx = new Dictionary<string, int>();
            flds.ForEach(x => fldidx.Add(x, pFeatureClass.FindField(x)));

            Dictionary<string, object> dic = new Dictionary<string, object>();
            List<Dictionary<string, object>> lis = new List<Dictionary<string, object>>();

            IFeatureCursor cursor = pFeatureClass.Search(queryFilter, true);
            IFeature feature = null;
            while ((feature = cursor.NextFeature()) != null)
            {
                fcount++;
                foreach (var it in fldidx)
                    dic[it.Key] = feature.Value[it.Value];
                if (!lis.Exists(x => x.SequenceEqual(dic)))
                    lis.Add(new Dictionary<string, object>(dic));
            }
            System.Runtime.InteropServices.Marshal.ReleaseComObject(cursor);
            return lis;
        }

 

2、使用枚举

 gdb: 耗时4972ms  mdb:3987ms    shp:7700ms

/// <summary>
/// 得到要素类某字段的唯一值
/// </summary>
/// <param name="pFeatureClass">要素类</param>
/// <param name="strFld">指定要得到唯一值的字段</param>
/// <returns>唯一值字符数据</returns>
public static List<string> GetUniqueValueWithEnum(IFeatureClass pFeatureClass, string strFld)
{
    //定义List泛型           
    List<string> plist = new List<string>();
    using (ComReleaser comReleaser=new ComReleaser())
    {
        //得到IFeatureCursor游标
        IFeatureCursor pCursor = pFeatureClass.Search(null, false);
        comReleaser.ManageLifetime(comReleaser);
        //coClass对象实例生成
        IDataStatistics pData = new DataStatisticsClass();
        pData.Field = strFld;
        pData.Cursor = pCursor as ICursor;
        //枚举唯一值
        IEnumerator pEnumVar = pData.UniqueValues;
        //可记录总条数:int RecordCount=pData.UniqueValueCount;
        pEnumVar.Reset();
        while (pEnumVar.MoveNext())
        {
            plist.Add(pEnumVar.Current.ToString());
        }
    } 
    return plist;
}

3、使用IQueryDef2接口

  gdb:耗时4390ms    mdb:178ms   shp:不支持

/// <summary>
/// 得到要素类唯一记录
/// </summary>
/// <param name="FClass"></param>
/// <param name="strFld">字段名(可以多个字段,以逗号相隔,例如:"DLBM,DLMC")</param>
/// <returns></returns>
public List<string> GetUniqueValueByQF(IFeatureClass FClass, string strFld)
{
    List<string> plist = new List<string>();
    Dictionary<string, string> dic = new Dictionary<string, string>();
    using (ComReleaser comReleaser = new ComReleaser())
    {
        IDataset dataset = FClass as IDataset;
        IFeatureWorkspace featureWorkspace = dataset.Workspace as IFeatureWorkspace;
        // Create the QueryDef.  
        IQueryDef2 queryDef2 = (IQueryDef2)featureWorkspace.CreateQueryDef();
        queryDef2.Tables = dataset.Name;
        queryDef2.SubFields = $"Distinct {strFld}";

        ICursor cursor = queryDef2.Evaluate2(true);
        comReleaser.ManageLifetime(cursor);
        int idx = 0;
        switch (dataset.Workspace.WorkspaceFactory.GetType().Name)
        {
            case "AccessWorkspaceFactoryClass":
                idx = cursor.FindField($"Distinct {strFld.Split(',')[0]}");  //在mdb中首个字段名会变为:$"Distinct XX"
                break;
            case "FileGDBWorkspaceFactoryClass":
                idx = cursor.FindField(strFld.Split(',')[0]);
                break;
        }
        var value = "";
        IRow row = null;
        while ((row = cursor.NextRow()) != null)
        {
            value = row.Value[idx].ToString();
            plist.Add(value);
                    
        }
    }
    return plist;
}

获取多字段唯一值:

        /// <summary>
        /// 得到要素类唯一记录
        /// </summary>
        /// <param name="FClass"></param>
        /// <param name="flds">字段集合</param>
        /// <param name="strWhere">限制条件</param>
        /// <returns></returns>
        public static List<Dictionary<string, object>> GetUniqueValueByQF(IFeatureClass FClass, List<string> flds,string strWhere="")
        {
            List<Dictionary<string, object>> pdic = new List<Dictionary<string, object>>();
            Dictionary<string, int> fldidx = new Dictionary<string, int>();
            string fls = string.Empty;
            for (int i = 0; i < flds.Count; i++)
            {
                fldidx[flds[i]] = i;
                fls += $",{flds[i]}";
            } 
            Dictionary<string, object> dic = new Dictionary<string, object>();
            using (ComReleaser comReleaser = new ComReleaser())
            {
                IDataset dataset = FClass as IDataset;
                IFeatureWorkspace featureWorkspace = dataset.Workspace as IFeatureWorkspace;
                // Create the QueryDef.  
                IQueryDef2 queryDef2 = (IQueryDef2)featureWorkspace.CreateQueryDef();
                queryDef2.Tables = dataset.Name;
                    
                queryDef2.SubFields = $"Distinct {fls.Substring(1)}";
                if (!string.IsNullOrEmpty(strWhere))
                    queryDef2.WhereClause = strWhere;

                ICursor cursor = queryDef2.Evaluate2(true);
                comReleaser.ManageLifetime(cursor);
                IRow row = null;
                while ((row = cursor.NextRow()) != null)
                {
                    foreach (var it in fldidx)
                        dic[it.Key] = row.Value[it.Value];
                    pdic.Add(new Dictionary<string, object>(dic));
                }
            }
            return pdic;
        }

 

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Geodatabase; namespace WindowsFormsApplication1 { public partial class Form2 : Form { private Form1 mainForm; // 主窗体引用 private ILayer selectedLayer; // 当前选中的图层 public Form2(Form1 form) { InitializeComponent(); mainForm = form; } private void Form2_Load(object sender, EventArgs e) { // 初始化图层列表 LoadLayers(); } // 加载图层到下拉列表 private void LoadLayers() { cboLayers.Items.Clear(); IMap map = mainForm.axMapControl1.Map; for (int i = 0; i < map.LayerCount; i++) { ILayer layer = map.get_Layer(i); cboLayers.Items.Add(layer.Name); } if (cboLayers.Items.Count > 0) { cboLayers.SelectedIndex = 0; } } // 获取当前选中的图层 private ILayer GetSelectedLayer() { if (cboLayers.SelectedIndex < 0) return null; string layerName = cboLayers.SelectedItem.ToString(); IMap map = mainForm.axMapControl1.Map; for (int i = 0; i < map.LayerCount; i++) { if (map.get_Layer(i).Name == layerName) { return map.get_Layer(i); } } return null; } // 图层选择改变时加载字段 private void cboLayers_SelectedIndexChanged(object sender, EventArgs e) { LoadFields(); } // 加载字段到字段下拉框 private void LoadFields() { cboFields.Items.Clear(); selectedLayer = GetSelectedLayer(); if (selectedLayer == null) return; IFeatureLayer featureLayer = selectedLayer as IFeatureLayer; if (featureLayer == null) return; IFeatureClass featureClass = featureLayer.FeatureClass; IFields fields = featureClass.Fields; for (int i = 0; i < fields.FieldCount; i++) { IField field = fields.get_Field(i); cboFields.Items.Add(field.Name); } if (cboFields.Items.Count > 0) { cboFields.SelectedIndex = 0; } } // 获取唯一值 private void btnGetUniqueValues_Click(object sender, EventArgs e) { selectedLayer = GetSelectedLayer(); if (selectedLayer == null) return; IFeatureLayer featureLayer = selectedLayer as IFeatureLayer; if (featureLayer == null) { MessageBox.Show("请选择一个要素图层"); return; } IFeatureClass featureClass = featureLayer.FeatureClass; if (cboFields.SelectedIndex < 0) { MessageBox.Show("请选择字段"); return; } string fieldName = cboFields.SelectedItem.ToString(); int fieldIndex = featureClass.FindField(fieldName); if (fieldIndex == -1) { MessageBox.Show($"字段 '{fieldName}' 不存在"); return; } // 获取唯一值 IDataStatistics dataStats = new DataStatisticsClass(); dataStats.Field = fieldName; ICursor cursor = featureClass.Search(null, true); dataStats.Cursor = cursor; IEnumerator enumerator = dataStats.UniqueValues; lstValues.Items.Clear(); while (enumerator.MoveNext()) { lstValues.Items.Add(enumerator.Current.ToString()); } } // 添加到查询条件 private void btnAddToQuery_Click(object sender, EventArgs e) { if (lstValues.SelectedItem != null) { string value = lstValues.SelectedItem.ToString(); string field = cboFields.SelectedItem.ToString(); if (!string.IsNullOrEmpty(field) && !string.IsNullOrEmpty(value)) { if (txtWhereClause.Text.Length > 0) { txtWhereClause.Text += " "; } txtWhereClause.Text += $"{field} = '{value}'"; } } } // 双击列表项添加到查询条件 private void lstValues_DoubleClick(object sender, EventArgs e) { if (lstValues.SelectedItem != null) { string value = lstValues.SelectedItem.ToString(); string field = cboFields.SelectedItem.ToString(); if (!string.IsNullOrEmpty(field) && !string.IsNullOrEmpty(value)) { if (txtWhereClause.Text.Length > 0) { txtWhereClause.Text += " "; } txtWhereClause.Text += $"{field} = '{value}'"; } } } // 验证查询条件 private void btnValidate_Click(object sender, EventArgs e) { selectedLayer = GetSelectedLayer(); if (selectedLayer == null) return; IFeatureLayer featureLayer = selectedLayer as IFeatureLayer; if (featureLayer == null) { MessageBox.Show("请选择一个要素图层"); return; } string whereClause = txtWhereClause.Text.Trim(); if (string.IsNullOrEmpty(whereClause)) { MessageBox.Show("查询条件不能为空"); return; } try { IQueryFilter queryFilter = new QueryFilterClass(); queryFilter.WhereClause = whereClause; // 尝试获取一个要素来验证查询 IFeatureCursor cursor = featureLayer.FeatureClass.Search(queryFilter, false); IFeature feature = cursor.NextFeature(); if (feature != null) { MessageBox.Show("查询条件有效"); } else { MessageBox.Show("查询条件有效,但没有匹配的记录"); } } catch (Exception ex) { MessageBox.Show($"查询条件无效: {ex.Message}"); } } // 应用查询 private void btnApply_Click(object sender, EventArgs e) { selectedLayer = GetSelectedLayer(); if (selectedLayer == null) return; IFeatureLayer featureLayer = selectedLayer as IFeatureLayer; if (featureLayer == null) { MessageBox.Show("请选择一个要素图层"); return; } string whereClause = txtWhereClause.Text.Trim(); if (string.IsNullOrEmpty(whereClause)) { MessageBox.Show("查询条件不能为空"); return; } try { IQueryFilter queryFilter = new QueryFilterClass(); queryFilter.WhereClause = whereClause; // 执行查询 IFeatureCursor cursor = featureLayer.FeatureClass.Search(queryFilter, false); IFeature feature; List<int> oidList = new List<int>(); // 获取所有符合条件的OID while ((feature = cursor.NextFeature()) != null) { oidList.Add(feature.OID); } // 在Form1中高亮显示 mainForm.HighlightFeatures(selectedLayer, oidList); // 加载属性数据 LoadAttributeData(featureLayer, queryFilter); MessageBox.Show($"找到 {oidList.Count} 条记录"); } catch (Exception ex) { MessageBox.Show($"查询失败: {ex.Message}"); } } // 加载属性数据到DataGridView private void LoadAttributeData(IFeatureLayer featureLayer, IQueryFilter queryFilter) { ITable table = featureLayer.FeatureClass as ITable; if (table == null) return; DataTable dataTable = new DataTable(); IFields fields = table.Fields; // 添加列 for (int i = 0; i < fields.FieldCount; i++) { IField field = fields.get_Field(i); dataTable.Columns.Add(field.AliasName, typeof(string)); } // 查询数据 ICursor cursor = table.Search(queryFilter, false); IRow row; int maxRecords = 1000; // 限制记录数 int recordCount = 0; while ((row = cursor.NextRow()) != null && recordCount < maxRecords) { DataRow dataRow = dataTable.NewRow(); for (int i = 0; i < fields.FieldCount; i++) { object value = row.get_Value(i); dataRow[i] = value == null ? string.Empty : value.ToString(); } dataTable.Rows.Add(dataRow); recordCount++; } dgvResults.DataSource = dataTable; } // 关闭窗体 private void btnClose_Click(object sender, EventArgs e) { this.Close(); } // 清除查询条件 private void btnClear_Click(object sender, EventArgs e) { txtWhereClause.Text = ""; } // 逻辑运算符按钮点击事件 private void OperatorButton_Click(object sender, EventArgs e) { Button btn = sender as Button; if (btn != null) { if (txtWhereClause.Text.Length > 0) { txtWhereClause.Text += " "; } txtWhereClause.Text += btn.Text + " "; } } // 括号按钮点击事件 private void btnParentheses_Click(object sender, EventArgs e) { Button btn = sender as Button; if (btn != null) { if (txtWhereClause.Text.Length > 0) { txtWhereClause.Text += " "; } txtWhereClause.Text += btn.Text; } } } }不改变代码内容,仅将美元符号的字符串插值,全部替换为format方法,因为我是vs2010版本不支持美元字符串插值
最新发布
07-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值