一、ArcGIS10新特性
1、 在ArcGIS10中新增了要素附件功能。要素附件即:在FeatureClass中的每一个Feature都可以关联一个或多个任意格式附件文件(如,文档文件、图片和视频文件等)。另一方面,在数据库中,如果删除了featureClass则与之对应要素附件也会被删除。
2、 ArcGIS中的要素附件管理的原理。
(1) 创建要素附件。
在ArcGIS10中,只能为要素类(FeatureClass)创建附件(即:一个要素类对应一个附件表和一个关系类)。具体创建方法见下图1:
图1 为要素类(图中为DISTR)创建附件。
创建附件后,会在数据库中自动创建一个表(Table)和关系类(RelationshhipClass),如下图2所示:
图2要素类DISTR及其附件表(DISTR_ATTACH)和关系类(DISTR_ATTACHREL)
(2) 添加附件。
在ArcMap中,加载已经创建了附件的要素图层,开启编辑,即可为每一个要素添加附件。如下图3和图4所示:
图3添加附件
图4添加任意格式的附件
(3) 查询附件。
在ArcMap中进行要素属性查询时,如果要素存在附件,可以再要素属性查询窗口中看到,如下图5所示:
图5 要素属性查询
(4) 附件表和关系类
附件表结构和关系类如下图6、7所示:
图6附件表
图7关系类
3、 ArcGIS10中新增的接口:ITableAttachments
(1) OMD图
(2) ITableAttachments、IAttachmentManager、IEnumAttachment、IAttachment等接口相关属性和方法,可以参考开发帮助
二、自定义实现要素附件管理(适用于ArcGIS 9.3和ArcGIS10)
尽管ArcGIS10提供了附件管理功能,但是在使用的时候并不是很方便,主要原因是:
1、只能只对一个要素类进行管理,即:一个要素类对应一个附件表和关系类。如果要对所有的要素类进行附件管理,就需要为每一个要素创建一个附件表和关系类,不能进行统一管理。
2、受版本限制,目前只能在ArcGIS10及以上版本中使用这个功能,对于10之前的版本就无能为力了。
鉴于上面的原因,我们可以基于ArcGIS10的附件管理原理,自定义实现要素的附件管理功能,这样我们可以突破限制,对所有的要素类的附件进行统一管理同时不受版本的限制(目前已经测试在10和9.3中均适用)。实现的过程比较简单,具体的方法:
在数据库中创建一个附件表,所有要素类和所有的附件都存放在这个附件表中,在增、删、查的时候只要操作这个附件表就行了。具体的表结构设计:
附件表
下面不多说了,贴代码:
public interface ISMFeatureAttachment { void SMAddAttachments();//添加附件表 bool SMHasAttachments{ get;}//判断是否存在附件表 void SMDeleteAttachments();//删除附件表 ISMAttachmentManager SMAttachmentManager { get; }//附件管理接口 } public interface ISMAttachmentManager { bool SMAddAttachment(ISMAttachment attachment);//添加附件 bool SMAddAttachment2(ISMAttachment attachment);//添加附件 bool SMDeleteAttachment(int attachmentID);//删除指定附件ID的附件 bool SMDeleteAttachmentForFeature(int featureID,string physicalLayerName);//删除指定要素的所有附件 void SMUpdateAttachment(ISMAttachment attachment);//更新附件 ISMEnumAttachment GetAttachmentByParentID(int featureID,bool IsOnlyInfo);//获取指定要素的所有附件 //ISMAttachment GetAttachmentByAttachmentID(int attachmentID);//获取指定附件ID的附件 IWorkspace Workspace { get; set; }//工作空间属性 string AttachmentTableName { get; set; }//附件表名属性 } public interface ISMAttachment { int AttachmentID { get; set; } int ParentID { get; set; } string ContentType { get; set; } IMemoryBlobStream Data { get; set; } uint DataSize { get; } string AttachmentName { get; set; } string PhysicalLayerName { get; set; } } public interface ISMEnumAttachment { ISMAttachment Next(); void Reset(); IWorkspace CurrentWorkspace{ get;set;} ITable AttachmentTable{ get;set;} ListAttachmentList { get;} }
////// 摘要:附件管理器 /// public class SMAttachmentManagerClass:ISMAttachmentManager { private int m_FeatureID; private IWorkspace m_Workspace; private string m_AttachmentTableName; ////// 构造函数 /// public SMAttachmentManagerClass() { } #region ISMAttachmentManager 成员 ////// 添加附件 /// /// 要素ID /// 附件对象 public bool SMAddAttachment(ISMAttachment attachment) { try { //打开附件表 ITable pTable = (this.Workspace as IFeatureWorkspace).OpenTable(this.m_AttachmentTableName); IRow pRow = pTable.CreateRow(); IFields fields = pRow.Fields; for (int i = 0; i < fields.FieldCount; i++) { IField field = pTable.Fields.get_Field(i); if (field.Name.ToUpper() == "OBJECTID") continue; switch (field.Name.ToUpper()) { case "PARENTID": pRow.set_Value(i, attachment.ParentID); break; case "ATTACHMENTNAME": pRow.set_Value(i, attachment.AttachmentName); break; case "CONTENTTYPE": pRow.set_Value(i, attachment.ContentType.ToString()); break; case "DATA": pRow.set_Value(i,(object)attachment.Data); break; case "DATASIZE": pRow.set_Value(i,attachment.DataSize); break; case "PHYSICALLAYERNAME": pRow.set_Value(i,attachment.PhysicalLayerName); break; default: break; } } pRow.Store(); return true; } catch (Exception ex) { return false; } } ////// 添加附件 /// /// 附件 ///public bool SMAddAttachment2(ISMAttachment attachment) { IRowBuffer rowBuffer = null; ICursor insertCursor = null; try { IWorkspaceEdit pWSEdit = this.Workspace as IWorkspaceEdit; //打开附件表 ITable pTable = (this.Workspace as IFeatureWorkspace).OpenTable(this.m_AttachmentTableName); IFields fields = pTable.Fields; pWSEdit.StartEditing(true); pWSEdit.StartEditOperation(); rowBuffer = pTable.CreateRowBuffer(); insertCursor = pTable.Insert(true); for (int i = 0; i < fields.FieldCount; i++) { IField field = rowBuffer.Fields.get_Field(i); if (field.Name.ToUpper() == "OBJECTID") continue; switch (field.Name.ToUpper()) { case "PARENTID": rowBuffer.set_Value(i, attachment.ParentID); break; case "ATTACHMENTNAME": rowBuffer.set_Value(i, attachment.AttachmentName); break; case "CONTENTTYPE": rowBuffer.set_Value(i, attachment.ContentType.ToString()); break; case "DATA": rowBuffer.set_Value(i, attachment.Data); break; case "DATASIZE": rowBuffer.set_Value(i, attachment.DataSize); break; case "PHYSICALLAYERNAME": rowBuffer.set_Value(i, attachment.PhysicalLayerName); break; default: break; } } insertCursor.InsertRow(rowBuffer); insertCursor.Flush(); pWSEdit.StopEditOperation(); pWSEdit.StopEditing(true); return true; } catch (Exception) { return false; } finally { if (rowBuffer != null) { System.Runtime.InteropServices.Marshal.ReleaseComObject(rowBuffer); } if (insertCursor != null) { System.Runtime.InteropServices.Marshal.ReleaseComObject(insertCursor); } } } /// /// 删除指定附件 /// /// public bool SMDeleteAttachment(int attachmentID) { string whereClause = string.Format("objectID={0}", attachmentID); DeletRows(whereClause); return true; } ////// 删除要素的所有附件 /// /// public bool SMDeleteAttachmentForFeature(int featureID,string physicalLayerName) { string whereClause = string.Format("ParentID={0} and PhysicalLayerName='{1}'",featureID,physicalLayerName); DeletRows(whereClause); return true; } ////// 更新附件 /// /// public void SMUpdateAttachment(ISMAttachment attachment) { //删除原始附件记录 string WhereClause = string.Format("OBJECTID={0}",attachment.AttachmentID); DeletRows(WhereClause); //添加附件 SMAddAttachment(attachment); } ////// 获取指定要素的所有附件 /// /// 要素ID ///public ISMEnumAttachment GetAttachmentByParentID(int featureID, bool IsOnlyInfo) { ITable pTable = (this.Workspace as IFeatureWorkspace).OpenTable(this.m_AttachmentTableName); ISMEnumAttachment enumAttachment = new SMEnumAttachmentClass(featureID,IsOnlyInfo,this.Workspace,pTable); return enumAttachment; } /// /// 工作空间 /// public IWorkspace Workspace { get { return this.m_Workspace; } set { this.m_Workspace = value; } } ////// 附件表名 /// public string AttachmentTableName { get { return this.m_AttachmentTableName; } set { this.m_AttachmentTableName = value; } } #endregion ////// 快速删除表中的行对象 /// /// private void DeletRows(string whereClause) { try { ITable pTable = (this.Workspace as IFeatureWorkspace).OpenTable(this.m_AttachmentTableName); IQueryFilter pQueryFilter = new QueryFilterClass(); pQueryFilter.WhereClause = whereClause; pTable.DeleteSearchedRows(pQueryFilter);//快速删除 } catch (Exception ex) { System.Windows.Forms.MessageBox.Show("异常来自:SMDeleteAttachment:\r\n" + ex.Message); } } } public class SMAttachmentClass:ISMAttachment { private IFeature m_Feature;//要素 private int m_AttachmentID;//附件ID private int m_ParentID;//要素ID private string m_ContentType;//附件内容类型 private IMemoryBlobStream m_Data;//附件 private uint m_DataSize;//附件大小 private string m_AttachmentName;//附件名称 private string m_PhysicalLayerName;//物理图层名 public SMAttachmentClass() {} #region ISMAttachment 成员 ////// 附件ID /// public int AttachmentID { get { return this.m_AttachmentID; } set { this.m_AttachmentID = value;} } ////// 要素ID /// public int ParentID { get { return this.m_ParentID; } set { this.m_ParentID=value; } } ////// 附件类型 /// public string ContentType { get { return this.m_ContentType; } set { this.m_ContentType = value; } } ////// 附件数据 /// public ESRI.ArcGIS.esriSystem.IMemoryBlobStream Data { get { return this.m_Data; } set { this.m_Data=value; } } ////// 附件大小 /// public uint DataSize { get { return this.m_Data.Size; } } ////// 附件名称 /// public string AttachmentName { get { return this.m_AttachmentName; } set { this.m_AttachmentName=value; } } ////// 物理图层名 /// public string PhysicalLayerName { get { return this.m_PhysicalLayerName; } set { this.m_PhysicalLayerName = value; } } #endregion } public class SMFeatureAttachmentClass:ISMFeatureAttachment { private IWorkspace m_Workspace; private string m_TableName; private ISMAttachmentManager m_AttachmentManager; ////// 构造函数 /// /// /// public SMFeatureAttachmentClass(IWorkspace ws,string tablename) { this.m_Workspace=ws; this.m_TableName = tablename;//附件表名 } #region ISMFeatureAttachment 成员 ////// 添加要素附件表 /// public void SMAddAttachments() { try { if (this.SMHasAttachments) { MessageBox.Show(string.Format("要素附件表【{0}】已经存在。", this.m_TableName), "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { IFields fields = this.CreateFiledCollectionForTable();//字段集合 if (fields != null) { if (this.CreateAttachmentTable(this.m_Workspace, this.m_TableName, fields)) { MessageBox.Show(string.Format("要素附件表【{0}】创建成功.", this.m_TableName), "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { MessageBox.Show(string.Format("要素附件表【{0}】创建失败.", this.m_TableName), "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { MessageBox.Show("初始化字段集合失败!"); } } } catch (Exception ex) { MessageBox.Show(string.Format("要素附件表【{0}】创建失败。原因:\r\n"+ex.Message, this.m_TableName), "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } } ////// 检查附件表是否存在 /// public bool SMHasAttachments { get { IWorkspace2 ws2 = this.m_Workspace as IWorkspace2; if (ws2.get_NameExists(esriDatasetType.esriDTTable, this.m_TableName)) { return true; } else { return false; } } } ////// 删除附件表 /// public void SMDeleteAttachments() { DeleteAttachmentTable(this.m_TableName);//删除附件表 } ////// 附件管理器 /// public ISMAttachmentManager SMAttachmentManager { get { if (this.m_AttachmentManager == null) { this.m_AttachmentManager = new SMAttachmentManagerClass(); m_AttachmentManager.Workspace = this.m_Workspace; m_AttachmentManager.AttachmentTableName = this.m_TableName; } return this.m_AttachmentManager; } } #endregion #region 辅助函数 ////// 创建附件表 /// /// 表名 private bool CreateAttachmentTable(IWorkspace workspace,string tablename,IFields fields) { try { IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace; IObjectClassDescription ocDescription = new ObjectClassDescriptionClass(); IFieldChecker fieldChecker = new FieldCheckerClass(); IEnumFieldError enumFieldError = null; IFields validatedFields = null; fieldChecker.ValidateWorkspace = workspace; fieldChecker.Validate(fields, out enumFieldError, out validatedFields); ITable table = featureWorkspace.CreateTable(tablename, validatedFields, ocDescription.InstanceCLSID, null, ""); return true; } catch (Exception) { return false; } } ////// 创建字段集合 /// private IFields CreateFiledCollectionForTable() { IFields pFields = new FieldsClass(); IFieldsEdit pFieldsEdit = pFields as IFieldsEdit; IField pField = null; //AttachmentID pField = new FieldClass(); IFieldEdit pFieldEdit = pField as IFieldEdit; pFieldEdit.Name_2 = "AttachmentID"; pFieldEdit.AliasName_2 = "附件ID"; pFieldEdit.Type_2 = esriFieldType.esriFieldTypeOID; pFieldsEdit.AddField(pField); //ParentID pField = new FieldClass(); IFieldEdit parentField = pField as IFieldEdit; parentField.Type_2 = esriFieldType.esriFieldTypeInteger; parentField.Name_2 = "ParentID"; parentField.AliasName_2 = "要素ID"; parentField.IsNullable_2 = false; pFieldsEdit.AddField(pField); //AttachmentName pField = new FieldClass(); IFieldEdit nameField = pField as IFieldEdit; nameField.Type_2 = esriFieldType.esriFieldTypeString; nameField.Name_2 = "AttachmentName"; nameField.AliasName_2 = "附件名称"; nameField.IsNullable_2 = false; pFieldsEdit.AddField(pField); //ContentType pField = new FieldClass(); IFieldEdit contentField = pField as IFieldEdit; contentField.Type_2 = esriFieldType.esriFieldTypeString; contentField.Name_2 = "ContentType"; contentField.AliasName_2 = "附件类型"; contentField.IsNullable_2 = false; pFieldsEdit.AddField(pField); //Data pField = new FieldClass(); IFieldEdit dataField = pField as IFieldEdit; dataField.Type_2 = esriFieldType.esriFieldTypeBlob; dataField.Name_2 = "Data"; dataField.AliasName_2 = "附件数据"; dataField.IsNullable_2 = false; pFieldsEdit.AddField(pField); //DataSize pField = new FieldClass(); IFieldEdit datasizeField = pField as IFieldEdit; datasizeField.Type_2 = esriFieldType.esriFieldTypeInteger; datasizeField.Name_2 = "DataSize"; datasizeField.AliasName_2 = "附件大小"; datasizeField.IsNullable_2 = false; pFieldsEdit.AddField(pField); //PhysicalLayerName pField = new FieldClass(); IFieldEdit layerField = pField as IFieldEdit; layerField.Type_2 = esriFieldType.esriFieldTypeString; layerField.Name_2 = "PhysicalLayerName"; layerField.AliasName_2 = "物理图层名"; layerField.IsNullable_2 = false; pFieldsEdit.AddField(pField); return pFields; } ////// 删除附件表 /// /// 表名 private void DeleteAttachmentTable(string tablename) { if (this.SMHasAttachments) { try { if (MessageBox.Show(string.Format("确定要删除附件表【{0}】吗?", this.m_TableName), "", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { ITable pTable = (this.m_Workspace as IFeatureWorkspace).OpenTable(this.m_TableName); ISchemaLock schemaLock = pTable as ISchemaLock; try { schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); IDataset ds = pTable as IDataset; ds.Delete(); } catch (Exception ex) { MessageBox.Show("删除附件表失败.原因:\r\n"+ex.Message,"错误提示",MessageBoxButtons.OK,MessageBoxIcon.Error); } finally { schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock); } } } catch (Exception ex) { MessageBox.Show("删除附件表失败!\r\n原因:"+ex.Message); } } } #endregion }
先贴部分代码吧,希望感兴趣的园友们可以一起讨论学习。水平有限,欢迎各位批评指正。