使用GP工具实现数据表连接功能
1 数据连接
1.1 在ArcMap图层中的应用
需要FeatureLayer
示例代码:
///IFeatureLayer 基准图层 ///ITable 要连接的表 ///mFeatureField 基准表中的链接字段 ///mTableField 外表链接的字段 ///返回链接关系结果类 public IFeatureClass FeatureJionTableFon(IFeatureLayer mFeatureLayer, ITable mTable, string mFeatureField, string mTableField) { inputFeatureClass = mFeatureLayer.FeatureClass; //得到基准要素类 FeatureTable = inputFeatureClass as ITable;//基准要素类转化为表 IRelationshipClass relationshipClass = memoryRelClassFactory.Open("", FeatureTable as IObjectClass, mFeatureField, mTable as IObjectClass, mTableField, "forward", "backward", esriRelCardinality.esriRelCardinalityOneToOne);//建立关系类 DisplayRelationshipClass = mFeatureLayer as IDisplayRelationshipClass;//显示关系类 DisplayRelationshipClass.DisplayRelationshipClass(relationshipClass, ESRI.ArcGIS.Geodatabase.esriJoinType.esriLeftInnerJoin); //基于指定的连接类型和关系类建立连接 displayTable = DisplayRelationshipClass as IDisplayTable;//显示表接口跳转 outputFeatureClass = displayTable.DisplayTable as IFeatureClass;//输出要素类接口跳转 return outputFeatureClass; }
对于上述代码,如果我们没有IFeatureLayer时,我们不能通过as语句,将IFeatureClass跳转为IFeatureLayer,而是应该先定义后赋值;故上述代码可改进为:
///IFeatureLayer 基准图层 ///ITable 要连接的表 ///mFeatureField 基准表中的链接字段 ///mTableField 外表链接的字段 ///返回链接关系结果类 public IFeatureClass FeatureJionTableFon(IFeatureClass baseFeatureClass, IFeatureClass srcFeatureClass, string baseFeatureField, string srcTableField) { // 1 创建一个内存关系类 Type memRelClassFactoryType = Type.GetTypeFromProgID( "esriGeodatabase.MemoryRelationshipClassFactory"); IMemoryRelationshipClassFactory memRelClassFactory = Activator.CreateInstance(memRelClassFactoryType) as IMemoryRelationshipClassFactory ; // 2 创建关系类 IRelationshipClass relationshipClass = memRelClassFactory.Open("数据连接", baseFeatureClass, baseFeatureField, srcFeatureClass, srcTableField, "", "", esriRelCardinality.esriRelCardinalityOneToOne); // 3 将关系类展示 IFeatureLayer pFeatureLayer = new FeatureLayerClass(); pFeatureLayer.FeatureClass = baseFeatureClass; IDisplayRelationshipClass pDisplayRelationshipClass = pFeatureLayer as IDisplayRelationshipClass;//显示关系类 pDisplayRelationshipClass.DisplayRelationshipClass(relationshipClass, ESRI.ArcGIS.Geodatabase.esriJoinType.esriLeftInnerJoin); //基于指定的连接类型和关系类建立连接 // 4 展示表转换为要素类 IDisplayTable displayTable = pDisplayRelationshipClass as IDisplayTable;//显示表接口跳转 return displayTable.DisplayTable as IFeatureClass;//输出要素类接口跳转 }
1.2 使用GP工具进行要素类连接--AddJoin
创建临时GDB文件,执行工具AddJoin建立要素连接,使用CopyFeatures工具拷贝链接结果
public AddJoin tableJoin(IFeatureClass editFeatureClass, IFeatureClass srcFeatureClass) { //1 创建gp工具 ESRI.ArcGIS.Geoprocessor.Geoprocessor pGeoprocessor = ESRI.ArcGIS.Geoprocessor.Geoprocessor{}; pGeoprocessor.OverwriteOutput = true; pGeoprocessor.AddOutputToMap = false; //2 创建GDB文件 CreateFileGDB processor = new CreateFileGDB {}; processor.out_folder_path = @"d:\临时目录"; processor.out_name = "temp.gdb"; pGeoprocessor.Execute(processor, null); //3 图层连接 AddJoin pAddJoin = new AddJoin { }; pAddJoin.in_layer_or_view = editFeatureClass; pAddJoin.in_field = "FEAID"; pAddJoin.join_table = srcFeatureClass as ITable; pAddJoin.join_field = "FEAID"; pAddJoin.join_type = "KEEP_ALL"; pGeoprocessor.Execute(pAddJoin, null); //4 图层拷贝 CopyFeatures pCopy = new CopyFeatures{}; pCopy.in_features = editFeatureClass; pCopy.out_feature_class = "d:\临时目录\temp.gdb\连接图层"; pGeoprocessor.Execute(pCopy , null); }
1.3 删除连接
/// <summary> /// 删除图层所有表连接(一次移除所有连接) /// </summary> /// <param name="pFeatureLayers"></param> public static void DeleteRelationships(IFeatureLayer pFeatureLayers) { ESRI.ArcGIS.DataManagementTools.RemoveJoin removeJoin = new ESRI.ArcGIS.DataManagementTools.RemoveJoin(pFeatureLayers); ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor(); IGeoProcessorResult gpResult = gp.Execute(removeJoin,null) as IGeoProcessorResult; }
X 帮助文档翻译
连接数据会将字段从一个或多个表追加到另一表。 ArcGIS提供了几种连接数据的方法。适当的方法取决于数据源和数据的基数。本主题描述了可用的选项以及如何确定最适合应用程序的选项。
X.1 查询表
查询表是虚拟表,代表涉及来自同一地理数据库或对象链接和嵌入数据库(OLE DB)数据源的一个或多个表的查询。 建立查询表时,可以基于主键制造一个ObjectID列。这允许表中具有ObjectID列的一对多联接;因此,支持选择。 创建查询表时,将根据是否涉及形状列来确定只读表或要素类返回。然后可以将其作为图层添加到ArcMap或用作任何其他只读表或要素类。该查询可以保存在图层文件或地图文档中。如果对查询中涉及的表进行了更改,则它们将反映在查询表中,因为它是虚拟表。 要获取查询表,请创建一个QueryDef对象,该对象定义了联接。然后可以调用IQueryDef.Evaluate方法来获取联接结果的游标。 请注意,QueryDef(以及随后的查询表)将仅返回已保存到数据库的行。如果应用程序处于编辑会话中,则该编辑会话中所做的更改将不会反映在QueryDef的结果中。 以下代码示例显示如何联接街道要素类(使用OBJECTID字段作为主键)和保存街道替代名称的表(替代名)(使用JOINID字段作为外键)
// Create the query definition. IQueryDef queryDef = featureWorkspace.CreateQueryDef(); // Provide a list of tables to join. queryDef.Tables = "streets, altname"; // Set the subfields and the WhereClause (in this case, the join condition). queryDef.SubFields = "streets.NAME, streets.TYPE, altname.ST_NAME, altname.ST_TYPE"; queryDef.WhereClause = "streets.OBJECTID = altname.JOINID"; // Get a cursor of the results and find the indexes of the fields to display. using(ComReleaser comReleaser = new ComReleaser()) { ICursor cursor = queryDef.Evaluate(); comReleaser.ManageLifetime(cursor); int streetsNameIndex = cursor.FindField("streets.NAME"); int streetsTypeIndex = cursor.FindField("streets.TYPE"); int altnameNameIndex = cursor.FindField("altname.ST_NAME"); int altnameTypeIndex = cursor.FindField("altname.ST_TYPE"); // Use the cursor to step through the results, displaying the names and altnames of each // street. IRow row = null; while ((row = cursor.NextRow()) != null) { Console.WriteLine("Street name: {0} {1}. - Alt. name: {2} {3}.", row.get_Value(streetsNameIndex), row.get_Value(streetsTypeIndex), row.get_Value(altnameNameIndex), row.get_Value(altnameTypeIndex)); } }
定义了QueryDef后,可以使用TableQueryName类创建查询表。以下代码示例显示了一个函数,该函数采用QueryDef,包含表的地理数据库工作区以及新查询表的名称。它还使用一个用于以逗号分隔的关键字段列表的参数来制造ObjectID。如果这不是一个选项,请将makeCopy参数(或CopyLocally属性)设置为true,并为关键字段提供一个空字符串。
// Make the new TableQueryName. IQueryName2 queryName2 = (IQueryName2)new TableQueryNameClass(); queryName2.QueryDef = queryDef; queryName2.PrimaryKey = "streets.StreetID"; queryName2.CopyLocally = true; // Set the workspace and name of the new QueryTable. IDatasetName datasetName = (IDatasetName)queryName2; datasetName.WorkspaceName = workspaceName; datasetName.Name = "StreetsJoin"; // Open the virtual table. IName name = (IName)queryName2; ITable table = (ITable)name.Open();
在ArcGIS 10及更高版本中,从同一ArcSDE或OLE DB数据源连接两个或多个数据集的开发人员可能要考虑使用查询类或查询游标。有关更多信息,请参见查询类和游标。
X.2 RelQueryTables
RelQueryTables用于连接来自不同数据源的表。例如,可以使用RelQueryTable将dBASE表连接到文件地理数据库要素类。
创建RelQueryTable需要两个表(或要素类)和一个关系类。关系类可以保留在地理数据库中,也可以创建为临时内存关系类。RelQueryTables不支持一对多联接。请参见下图:
RelQueryTables与查询表一样,都是只读的并且是虚拟的,因为对基本表的更改反映在RelQueryTable中。
与工作空间工厂一样,MemoryRelationshipClassFactory和RelQueryTableFactory类都是单例组件对象模型(COM)类,不应在.NET中使用new关键字实例化;而是应使用Activator.CreateInstance方法实例化它们,并使用Type.GetTypeFromProgID创建Type实例。有关更多信息,请参见与单例对象交互。
以下代码示例显示如何将宗地要素类和所有者表结合在一起以创建RelQueryTable:
// Build a memory relationship class. Type memRelClassFactoryType = Type.GetTypeFromProgID( "esriGeodatabase.MemoryRelationshipClassFactory"); IMemoryRelationshipClassFactory memRelClassFactory = (IMemoryRelationshipClassFactory)Activator.CreateInstance(memRelClassFactoryType) ; IRelationshipClass relationshipClass = memRelClassFactory.Open("ParcelsOwners", parcelsFeatureClass, "PARCEL_ID", (IObjectClass)ownersTable, "PARCEL_ID", "Is Owned By", "Owns", esriRelCardinality.esriRelCardinalityOneToOne); // Open the RelQueryTable as a feature class. Type rqtFactoryType = Type.GetTypeFromProgID("esriGeodatabase.RelQueryTableFactory"); IRelQueryTableFactory rqtFactory = (IRelQueryTableFactory)Activator.CreateInstance (rqtFactoryType); ITable relQueryTable = (ITable)rqtFactory.Open(relationshipClass, false, null, null, String.Empty, false, false);
删除满足where语句的要素的所有关系
This C# example deletes all the relationships for features satisfying the where clause parameter. public void DelRelationships(IRelationshipClass relationshipClass, IFeatureClass featureClass, string whereClause) { // Get the features whose relationships you want to delete IQueryFilter queryFilter = new QueryFilterClass(); queryFilter.WhereClause = whereClause; IFeatureCursor featureCursor = featureClass.Search(queryFilter, false); IFeature feature = null; ISet featureSet = new ESRI.ArcGIS.esriSystem.SetClass(); while ((feature = featureCursor.NextFeature()) != null) { featureSet.Add(feature); } // Delete the relationships featureSet.Reset(); Console.WriteLine("Count {0}", featureSet.Count); relationshipClass.DeleteRelationshipsForObjectSet(featureSet); }
外表关联:
ITable dispTable=((IDisplayTable)feaLayer).DisplayTable ;//图层 ITable attTable;//外表 IMemoryRelationshipClassFactory fac=new MemoryRelationshipClassFactoryClass (); IRelationshipClass relClass=fac.Open("JZMJ",(IObjectClass)dispTable,"ZDDJH", IObjectClass)attTable,"G03", "Forward","Backward", esriRelCardinality.esriRelCardinalityOneToOne); IDisplayRelationshipClass dispRelClass=feaLayer as IDisplayRelationshipClass ; dispRelClass.DisplayRelationshipClass(relClass,esriJoinType.esriLeftInnerJoin);