在之前的文章【ArcGIS Pro二次开发】(19):创建要素类(FeatureClass)中有涉及DDL的知识点,随着深入的学习,在这里做一个小总结。
一、DDL基本概念
ArcGIS Pro二次开发中的DDL API是一种【数据定义语言】,主要是用于创建、删除、编辑地理数据库以及地理数据库的部件(item),如要素类(FeatureClass)、表(Table)等。
1、Description类
DDL中有一个很重要的类:Description类,即描述类。主要用于指定要创建、修改或删除的数据库存对象。例如,【TableDescription】用来描述一个表。【TableDescription】有多个属性,其中一个属性【FieldDescriptin】则是用来描述字段的构成。
下面是一个【FieldDescriptin】的基本结构,其中【"InspectionDate"】是字段名, 【FieldType.Date】是字段类型,通俗的说,这两个属性相当于字段的主属性,是必须要有的属性,而后面属性列表中的【AliasName】是别名,相当于非必要属性,如果不定义的话,会采用默认值:
FieldDescription inspectionDateFieldDescription = new FieldDescription("InspectionDate", FieldType.Date)
{
AliasName = "Inspection Date"
};
2、SchemaBuilder对象
SchemaBuilder对象(方案构建器?好难翻译),是在地理数据库内部构建的一个对象,用于DDL操作。可以将DDL操作加入SchemaBuilder对象中,按照一定的逻辑顺序执行操作。
例如:先创建SchemaBuilder对象:
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
再将表的创建添加到我们的DDL任务列表中:
schemaBuilder.Create(tableDescription);
注意这里可以添加多个任务到任务列表中。
然后,通过调用 Build方法来执行这组DDL操作。结果可以返回一个bool值,显示是否执行成功。
bool success = schemaBuilder.Build();
以下是官方文档中记录的SchemaBuilder对象的所有成员和方法:
二、要素类(FeatureClass)、表(Table)的操作
1、创建FeatureClass、Table
以创建Table首先,创建一系列字段描述对象【FieldDescriptin】。
一个【FieldDescriptin】描述一个字段,一个FeatureClass或Table通常有多个字段,所以我们需要的是多个【FieldDescriptin】的列表。
创建字段可以从头创建,也可以基于已有字段,示例如下:
// 从头创建一个字段描述
FieldDescription inspectionDateFieldDescription = new FieldDescription("InspectionDate", FieldType.Date)
{
AliasName = "Inspection Date"
};
// 从已有的字段创建一个域字段描述
FieldDescription inspectionResultsFieldDescription = FieldDescription.CreateDomainField("InspectionResults", new CodedValueDomainDescription(inspectionResultsDomain));
inspectionResultsFieldDescription.AliasName = "Inspection Results";
创建所需的字段描述对象集后,下一步是创建一个定义表本身的表描述对象【TableDescription】。
【TableDescription】用于传递给【SchemaBuilder.Create】,通过【SchemaBuilder.Create】实现创建表的功能。
具体流程如下:
// 收集所有字段描述的列表
List<FieldDescription> fieldDescriptions = new List<FieldDescription>()
{ globalIDFieldDescription, objectIDFieldDescription, inspectionDateFieldDescription, inspectionResultsFieldDescription, inspectionNotesFieldDescription };
// 创建一个【tableDescription】对象来描述要创建的表
TableDescription tableDescription = new TableDescription("PoleInspection", fieldDescriptions);
// 创建一个【SchemaBuilder】对象
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
// 将创建任务添加到DDL任务列表中
schemaBuilder.Create(tableDescription);
// 执行DDL
bool success = schemaBuilder.Build();
需要注意的是,上面的流程并没有添加ObjectID字段,执行结果,会自动添加ObjectID字段。
创建FeatureClass遵循与创建Table大致相同的原则。不过需要注意的是,你需要额外创建一个 【ShapeDescription】对象来定义shape字段。
【ShapeDescription】对象可以从一组特性创建,也可以使用现有要素类的【FeatureClassDefinition】创建。在这种情况下,新要素类将继承现有类的相同形状特性。
// 创建一个【ShapeDescription】对象
ShapeDescription shapeDescription = new ShapeDescription(GeometryType.Point, spatialReference);
// 或者,可以从另一个要素类创建【ShapeDescription】
ShapeDescription alternativeShapeDescription = new ShapeDescription(existingFeatureClass.GetDefinition());
最后一步则是创建【FeatureClassDescription】,并使用上面描述的相同模式构建要素类。具体如下:
// 创建一个【FeatureClassDescription】对象来描述要创建的要素类
FeatureClassDescription featureClassDescription = new FeatureClassDescription("Cities", fieldDescriptions, shapeDescription);
// 创建一个【SchemaBuilder】对象
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
// 将创建任务添加到DDL任务列表中
schemaBuilder.Create(featureClassDescription);
// 执行DDL
bool success = schemaBuilder.Build();
2、修改FeatureClass、Table
以给FeatureClass添加2个新字段为例。
首先,创建一个新的【FeatureClassDescription】。Name属性和【ShapeDescription】就用原有要素的,【FieldDescription】则是在继承原有的基础上,添加2个新字段,然后再替换掉原来的【FieldDescription】进行更新。具体代码如下:
// 要修改的要素
string featureClassName = "Parcels";
// 获取待修改要素的【FeatureClassDefinition】
FeatureClassDefinition originalFeatureClassDefinition = geodatabase.GetDefinition<FeatureClassDefinition>(featureClassName);
// 获取【FeatureClassDescription】
FeatureClassDescription originalFeatureClassDescription = new FeatureClassDescription(originalFeatureClassDefinition);
// 定义需要添加的2个字段
FieldDescription taxCodeDescription = FieldDescription.CreateIntegerField("Tax_Code");
FieldDescription addressDescription = FieldDescription.CreateStringField("Parcel_Address", 150);
// 将2个新字段添加到【FieldDescription】列表中
List<FieldDescription> modifiedFieldDescriptions = new List<FieldDescription>(originalFeatureClassDescription.FieldDescriptions);
modifiedFieldDescriptions.Add(taxCodeDescription);
modifiedFieldDescriptions.Add(addressDescription);
// 使用新添加的字段创建一个【FeatureClassDescription】
FeatureClassDescription modifiedFeatureClassDescription = new FeatureClassDescription(originalFeatureClassDescription.Name, modifiedFieldDescriptions, originalFeatureClassDescription.ShapeDescription);
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
// 更新【Parcels】要素
schemaBuilder.Modify(modifiedFeatureClassDescription);
bool modifyStatus = schemaBuilder.Build();
// 如果出现错误,返回
if (!modifyStatus)
{
IReadOnlyList<string> errors = schemaBuilder.ErrorMessages;
}
3、重命名FeatureClass、Table
重命名表格或要素类,请创建与要重命名的表格或要素类匹配的【Description】对象。然后在【SchemaBuilder】类上调用Rename方法,代码如下:
// 定义原Name和要重命名的Name
string tableToBeRenamed = "Original_Table";
string tableRenameAs = "Renamed_Table";
// 获取要重命名的表的【TableDefinition】
TableDefinition tableDefinition = geodatabase.GetDefinition<TableDefinition>(tableToBeRenamed);
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
// 调用Rename方法即可重命名
schemaBuilder.Rename(new TableDescription(tableDefinition), tableRenameAs);
// 执行DDL
schemaBuilder.Build();
4、添加和删除字段
这里添加字段的方法和上面第2节使用的方法大致相同。
// 从现有表中获取【TableDescription】
TableDescription tableDescription = new TableDescription(parcelTableDefinition);
// 获取【FieldDescriptions】
List<FieldDescription> fieldDescriptions = new List<FieldDescription> (tableDescription.FieldDescriptions);
// 往【FieldDescriptions】中添加字段
fieldDescriptions.Add(FieldDescription.CreateIntegerField("FloodRiskScale"));
// 修改【TableDescription】
TableDescription modifiedTableDescription = new TableDescription(tableDescription.Name, fieldDescriptions);
// 更新【TableDescription】
schemaBuilder.Modify(modifiedTableDescription);
// 执行DDL
schemaBuilder.Build();
删除字段方法如下:
// 从现有表中获取【TableDescription】
TableDescription tableDescription = new TableDescription(parcelTableDefinition);
// 定义要保留的字段
FieldDescription taxFieldToBeRetained = new FieldDescription(parcelTableDefinition.GetFields().First(f => f.Name.Equals("TaxCode")));
List<FieldDescription> fieldsToBeRetained = new List<FieldDescription> { taxFieldToBeRetained };
// 修改【TableDescription】
TableDescription modifiedTableDescription = new TableDescription(tableDescription.Name, fieldsToBeRetained);
// 更新【TableDescription】
schemaBuilder.Modify(modifiedTableDescription);
// 执行DDL
schemaBuilder.Build();
5、修改现有字段的属性
可以使用SchemaBuilder.Modify(TableDescription、String、FieldDescription)方法修改表或要素类中某些现有字段的字段属性,如名称、别名、长度和类型。
但是需要注意,有些固有字段是不能修改的,如ObjestID,Shape_Area等。
还有就是别名的最大长度为255个字符,地理数据库中不允许使用空字符串作为别名。
示例代码如下:
// 获取要修改的字段【Parcel_Address】
Field parcelAddress = featureClassDefinition.GetFields().FirstOrDefault(f => f.Name.Contains("Parcel_Address"));
// 更新字段的别名和长度
FieldDescription newParcelFieldDescription = new FieldDescription(parcelAddress)
{
AliasName = "Physical Property Address",
Length = 250
};
// 设置默认的字段值
newParcelFieldDescription.SetDefaultValue("123 Main St");
schemaBuilder.Modify(new TableDescription(featureClassDefinition), parcelAddress.Name, newParcelFieldDescription);
schemaBuilder.Build();
6、删除FeatureClass、Table
要删除FeatureClass、Table只需要使用【SchemaBuilder.Delete】方法即可,其它的步骤和上面都差不多。
// 获取【tableDescription】
TableDescription tableDescription = new TableDescription(table.GetDefinition());
// 创建【SchemaBuilder】对象
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
// 调用【Delete】方法
schemaBuilder.Delete(tableDescription);
// // 执行DDL
bool success = schemaBuilder.Build();
三、文件地理数据库(GDB)的操作
1、创建和删除文件地理数据库
创建和删除文件地理数据库遵循的模式与其他DDL操作略有不同。可以调用【SchemaBuilder】类上的【CreateGeodatabase】和【DeleteGeodatabase】方法来创建和删除文件地理数据库。
这两个方法都以【FileGeodatabaseConnectionPath】作为参数,即文件路径。
需要注意的是,如果文件地理数据库正在使用中,则无法将其删除。所有对文件地理数据库的执行工作都必须在删除前完成。
// 创建【SchemaBuilder】对象
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
// 调用【CreateGeodatabase】方法创建数据库
schemaBuilder.CreateGeodatabase(GeodatabasePath);
// 执行DDL
bool success = schemaBuilder.Build();