目录
1. ArcCatalog创建GDB、MDB、SHP
2. 代码创建gdb工作空间
2.1 CreateFileGDB Class创建
2.2 Acrivator.CreateInstance创建
2.2.1 实现代码
2.2.2 空间索引格网大小无效异常及解决方案
2.2.3 完善代码
3 GDB目录删除与资源释放
3.1 删除gdb文件
3.2 资源解除占用
3.2.1 杀死文件:
3.2.2 解除资源锁定:
3.2.3 资源释放问题
4 从gdb中拷贝图层到mdb中
4.1 从gdb中获取感兴趣图层
4.2 获取gdb感兴趣图层的图层名
4.3 打开mdb文件
4.4 判断要拷贝到mdb的文件是否存在
4.5 输出mdb图层名设置
4.6 字段赋值
4.7 设置几何定义
4.8 满足条件的数据查询
4.9 数据转换
1. ArcCatalog创建GDB、MDB、SHP
- 打开arccatalog
- 选择要建库的位置——右键——新建
- 文件地理数据库就是格式为gdb的数据
- 个人地理数据库就是格式为mdb的数据
- shapefile就是格式为shp的数据
2. 代码创建gdb工作空间
2.1 CreateFileGDB Class创建
Creates a file geodatabase in a folder. [在给定目录下创建一个地理数据库]
//创建GDB文件对象
CreateFileGDB process1 = new CreateFileGDB {out_folder_path = @"D:\新建文件夹", out_name = "temp.gdb"}
注意上述代码中为out_folder_path设定的目录必须是已存在的目录,否则在使用GP工具执行时,会报错:对COM组件的调用返回了错误 HRESULT E_FAIL
GP.Execute(processor1, null);//将创建的GDB文件加入到GP工具中
2.2 Acrivator.CreateInstance创建
2.2.1 实现代码
/// <summary>
/// 在指定目录下创建gdb文件
/// </summary>
/// <param name="path">创建目录</param>
/// <returns>返回工作空间</returns>
public static IWorkspace CreateFileGdbWorkspace(string gdbFileName)
{
Type factoryType = Type.GetTypeFromProgID(
"esriDataSourcesGDB.FileGDBWorkspaceFactory");
IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance
(factoryType);
string path = System.IO.Path.GetDirectoryName(gdbFileName);
string fileName = System.IO.Path.GetFileName(gdbFileName);
IWorkspaceName workspaceName = workspaceFactory.Create(path, fileName, null, 0);
IName name = (IName)workspaceName;
IWorkspace workspace = (IWorkspace)name.Open();
return workspace;
}
2.2.2 空间索引格网大小无效异常及解决方案
- 错误:空间索引格网大小无效
- 当通过 CreateFeature 和 Store 方法或使用 InsertCursor 创建新要素时,可能发生以下错误而导致创建失败:“FDO_E_INVALID_GRID_SIZE -2147216894 空间索引格网大小无效。”
- 原因: 在创建要素的要素类的格网过小而无法处理要素,所以将出现 FDO_E_INVALID_GRID_SIZE 错误。 仅在使用文件地理数据库或 ArcSDE 地理数据库时会发生此错误。
根据错误消息出现方式的不同,可采用两种不同的方式来处理此错误。
- 如果在 ArcMap 中进行编辑时出现此错误,可重新计算或修改要素类的格网大小以容纳新要素。 必须在 ArcCatalog 的“要素类”属性对话框中重新计算格网大小。 此操作需要使用“停止编辑”功能,保存一切更改并关闭包含要素类的地图文档。 有关如何重新计算或修改要素类格网大小的步骤,请参阅以下 Web 帮助文档:设置空间索引。
- 如果在 ArcObjects API 中以编程方式遇到此错误,则通知用户手动修改空间索引不是理想的解决方案。 相反,可以在插入要素之前将要素类置于 LoadOnly 模式,以避免发生此错误。 当要素类退出 LoadOnly 模式时,地理数据库将自动重新计算适合的格网大小。 以下代码示例演示了如何将 LoadOnly 模式与要素类配合使用:
2.2.3 完善代码
IQueryFilter filter = new QueryFilterClass();
filter.WhereClause = "";
IFeatureCursor pFeaturnCuesor = srcFeatureClass.Search(filter, false);
IFeature pFeature = pFeaturnCuesor.NextFeature();
IFeatureClassLoad dstFeaLoad = dstFeatureClass as IFeatureClassLoad;
dstFeaLoad.LoadOnlyMode = true;
while (pFeature != null)
{
IFeature dstFea = dstFeatureClass.CreateFeature();
dstFea.Shape = pFeature.Shape;
dstFea.Store();
pFeature = pFeaturnCuesor.NextFeature();
}
3 GDB目录删除与资源释放
3.1 删除gdb文件
gdb实际上是一个文件夹,所以要使用文件夹删除的方式删除
///dir为要删除的文件夹
public void deleteDir(string dir)
{
try
{
Directory.Delete(dir, true);
}
catch
{
foreach (string file in Directory.GetFiles(dir))
{
FileInfo info = new FileInfo(file);
info.Attributes = FileAttributes.Normal;
File.Delete(file);
}
Directory.Delete(dir);
}
}
代码二:
将IWorkspace转为IDataset,然后使用IDataset.Delete();进行删除。最好不要使用System.IO.File.Delete(path); 根据mdb或FileGDB的路径删除,这种方法可能删除不掉或者删不干净。
IDataset dataset = pWorkspace as IDataset;
dataset.Delete();
注意:删除该workspace之前需要将使用到的FeatureClass,Feature,FeatureCursor,Field等AO对象先释放掉,可以使用System.Runtime.InteropServices.Marshal.FinalReleaseComObject();释放。
IWorkspaceFactory pWF = new FileGDBWorkspaceFactoryClass();
IWorkspace pW = pWF.OpenFromFile(gdbPath);
IFeatureWorkspace pWorkspace = pW as IFeatureWorkspace;
.....
IDataset dataset = pWorkspace as IDataset;
dataset.Delete();
3.2 资源解除占用
3.2.1 杀死文件:
Process[] pcs = Process.GetProcesses();
foreach (Process p in pcs)
{
if (p.MainModule.FileName == "你的文件路径")
{
p.Kill();
}
}
3.2.2 解除资源锁定:
ArcEngine /AO创建IWorkSpaceFactory的两种方式:
//第一种使用ae的工厂方法:
IWorkspaceFactory pWsFactory = new ShapefileWorkspaceFactoryClass();
IFeatureWorkspace pWorkSpace = pWsFactory.OpenFromFile(path, 0) as IFeatureWorkspace;
//第二种使用C#的动态创建类型的方法:
Type typeObj=Type .GetTypeFromProgID("esriWorkspaceType.ShapefileWorkspaceFactoryClass" );
IWorkspaceFactory pWsFactory = (IWorkspaceFactory)Activator.CreateInstance(typeObj,null);
IFeatureWorkspace pWorkSpace = pWsFactory.OpenFromFile(path, 0) as IFeatureWorkspace;
//关闭资源锁定
IWorkspaceFactoryLockControl ipWsFactoryLock = IWorkspaceFactoryLockControl)pWsFactory; //pWsFactory可以是GDB/SHP/MDB
if(ipWsFactoryLock.SchemaLockingEnabled)
{
ipWsFactoryLock.DisableSchemaLocking();
}
3.2.3 资源释放问题
AE中对MDB,SDE等数据库操作时,打开后却往往不能及时释放资源,导致别人操作提示对象被锁定。很多帖子说了很多原理,看的也烦且不实用,比如一句话概括的用System.Runtime.InteropServices.Marshal.ReleaseComObject(object o) 释放,说的很不清楚,很多人试过觉的释放不掉。事实上,的确是用该方法,但释放的技巧在于,新建几个AE对象就要逐步释放几个,例如:
IWorkspaceFactory Fact = new AccessWorkspaceFactoryClass ();
IFeatureWorkspace Workspace = Fact.Open(Propset,0) as IFeatureWorkspace;
IFeatureClass Fcls = Workspace.OpenFeatureClass ("District");
IFeatureLayer Fly = new FeatureLayerClass();
……
IFeature pf
IField pfield
……
再对象运行结束时释放,如:
System.Runtime.InteropServices.Marshal.ReleaseComObject(Fact)
System.Runtime.InteropServices.Marshal.ReleaseComObject(Workspace);
System.Runtime.InteropServices.Marshal.ReleaseComObject(Fcls);
System.Runtime.InteropServices.Marshal.ReleaseComObject(Fly);
System.Runtime.InteropServices.Marshal.ReleaseComObject(pf);
System.Runtime.InteropServices.Marshal.ReleaseComObject(pfield);
看到吧,千万不要以为你释放了等级最高的 IWorkspaceFactory, IWorkspace就算完事了。没办法,AE有时就这么难以理解的麻烦。
4 从gdb中拷贝图层到mdb中
主要是为了调用 IFeatureDataConverter.ConvertFeatureClass 方法:
public IEnumInvalidObject ConvertFeatureClass (
IFeatureClassNameInputDatasetName,
IQueryFilterInputQueryFilter,
IFeatureDatasetNameoutputFDatasetName,
IFeatureClassNameoutputFClassName,
IGeometryDefOutputGeometryDef,
IFieldsOutputFields,
stringconfigKey,
intFlushInterval,
intparentHWND);
为了给该函数提供参数,进行如下步骤拆解:
- 从gdb中获取感兴趣图层
- 从gdb中获取感兴趣图层的名称
- 打开mdb文件
- 判断要拷贝文件是否存在,存在删除
- 将gdb待拷贝图层字段赋值到mdb目标图层
- 设置集合定义
- 设置查询条件
- 调用转换函数
4.1 从gdb中获取感兴趣图层
- 打开工作空间工厂
- 从文件中打开工作空间,将工作空间跳转为要素工作空间
- 从要素工作空间中打开要素类
IWorkspaceFactory workspaceFactory = new ESRI.ArcGIS.DataSourcesGDB.FileGDBWorkspaceFactoryClass();
IWorkspace iworkspace = iworkspaceFactory.OpenFromFile(inPath, 0);
IFeatureWorkspace ifeatureWorkspace = (IFeatureWorkspace)iworkspace;
IFeatureClass ipFeaterClass = ifeatureWorkspace.OpenFeatureClass(checkLayerName);
4.2 获取gdb感兴趣图层的图层名
IWorkspaceName inWorkspaceName = (inWorkspace as IDataset).FullName as IWorkspaceName ;
IFeatureClassName inFeatureClassName = new FeatureClassNameClass();
IDatasetName inDatasetName = (IDatasetName)inFeatureClassName;
inDatasetName.WorkspaceName = inWorkspaceName;
inDatasetName.Name = gdbLayerName;
4.3 打开mdb文件
IWorkspaceFactory oworkspaceFactory = new AccessWorkspaceFactory();
IWorkspace oworkspace = oworkspaceFactory.OpenFromFile(inPath, 0);
IFeatureWorkspace ofeatureWorkspace = (IFeatureWorkspace)workspace;
IFeatureClass poFeaterClass = ofeatureWorkspace.OpenFeatureClass(mdbLayerName);
4.4 判断要拷贝到mdb的文件是否存在
IWorkspace2 oworkspace2 = (IWorkspace2)oworkspace;
if (oworkspace2.get_NameExists(esriDatasetType.esriDTFeatureClass, checkLayerName + "_超出图层检查结果"))
{
IFeatureClass pFC = ofeatureWorkspace.OpenFeatureClass(checkLayerName + "_超出图层检查结果");
IDataset pDS = pFC as IDataset;
pDS.Delete();
}
4.5 输出mdb图层名设置
IWorkspaceName ouWorkspaceName = (ouWorkspace as IDataset).FullName as IWorkspaceName ;
IFeatureClassName ouFeatureClassName = new FeatureClassNameClass();
IDatasetName ouDatasetName = (IDatasetName)ouFeatureClassName;
ouDatasetName.WorkspaceName = ouWorkspaceName;
ouDatasetName.Name = mdbLayerName;
4.6 字段赋值
IFieldChecker fieldChecker = new FieldCheckerClass();
fieldChecker.InputWorkspace = iworkspace;//输入数据集工作空间
fieldChecker.ValidateWorkspace = ouWorkpace;//输出工作空间
IFields outFeatureClassFields;
IEnumFieldError enumFieldError;
fieldChecker.Validate(inFeatureClassFields, out enumFieldError, out outFeatureClassFields);
4.7 设置几何定义
IField geometryField = outFeatureClassFields.get_Field(outFeatureClassFields.FindField(inFeatureClass.ShapeFieldName));
IGeometryDef geometryDef = geometryField.GeometryDef;
4.8 满足条件的数据查询
//Set up the IQueryFilter to convert all the features by leaving a blank WhereClause
QueryFilter qf = new QueryFilterClass();
qf.WhereClause = "";
4.9 数据转换
IFeatureDataConverter fctofc = new FeatureDataConverterClass();
IEnumInvalidObject enumErrors = fctofc.ConvertFeatureClass(inFeatureClassName, qf, null, outFeatureClassName, geometryDef, outFeatureClassFields, "", 1000, 0);
参考资料:从FileGDB导出shp
5 其他代码积累
5.1 添加或删除字段
/// <summary>
/// 删除属性表字段
/// </summary>
/// <param name="layer">需要添加字段的IFeatureLayer</param>
/// <param name="fieldName">添加的字段的名称</param>
/// <returns></returns>
static public bool DeleteField(IFeatureLayer layer, string fieldName)
{
try
{
ITable pTable = (ITable)layer;
IFields pfields;
IField pfield;
pfields = pTable.Fields;
int fieldIndex = pfields.FindField(fieldName);
pfield = pfields.get_Field(fieldIndex);
pTable.DeleteField(pfield);
return true;
}
catch (Exception ex)
{
return false;
}
}
/// <summary>
/// 添加字段
/// </summary>
/// <param name="layer"></param>
/// <param name="fieldName"></param>
/// <param name="filedType"></param>
/// <param name="fieldLength"></param>
/// <returns></returns>
static public bool AddField(IFeatureLayer layer, string fieldName, esriFieldType filedType, int fieldLength)
{
try
{
IFields pFields = layer.FeatureClass.Fields;
// IFieldsEdit pFieldsEdit = pFields as IFieldsEdit;
IFieldEdit pFieldEdit;
pFieldEdit = new FieldClass();
if (fieldName.Length > 5)
pFieldEdit.Name_2 = fieldName.Substring(0, 5);
else
pFieldEdit.Name_2 = fieldName;
pFieldEdit.Type_2 = filedType;
pFieldEdit.Editable_2 = true;
pFieldEdit.AliasName_2 = fieldName;
pFieldEdit.Length_2 = fieldLength;
ITable pTable = (ITable)layer;
pTable.AddField(pFieldEdit);
return true;
// pFieldsEdit.AddField((IField)pFieldEdit);
}
catch (Exception ex)
{
return false;
}
}