2023年11月23日发(作者:)

很多刚入门的朋友对SDE数据并不太了解,接二连三的在社区里面发问,有时也得不到很好的

解答,对此懒羊羊也深感同情。想到刚入门时的痛苦,懒羊羊决定抽写时间出来详细的讲述如何

去编辑SDE数据,希望可以跟广大新手一同成长,度过入门的艰难时期。如有错误或表述含糊

的地方,还请众高手指正。

SDEESRI开发的一个空间数据引擎,能够利用文件数据库良好的管理优势去管理数据的图

形和属性。AccessDatabase 与后来的 FileGeoDataBase同样也能够很好的管理数据,但是

SDE数据库最大差别是它们不支持多用户同时编辑,也就是SDE的版本技术。虽然大家都

知道这些,但是懒羊羊还是要顺便提一下。

很多人第一次接触SDE数据的时候思想可能还停留在对shp文件或是MDB文件的操作上面。

事实上它们大部分的操作时一致的,但接入的方式有所不同。由于SDE多了一个版本的控制,

所以在数据的载入与打开FeatureClass的时候有很大的差别。下面开始转入正题,讲述一下如

何对SDE数据进行操作。

1.

打开SDE数据。

SDE数据一定要使用工作空间工厂去初始化工作空间,在工作空间打开FeatureClass这是最

常规的操作。下面通过一段C#代码连接SDE,打开并返回一个IWorkspace

public IWorkspace FindWsByDefault()

{

IPropertySet propSet = new PropertySetClass();

perty("Server", Lan);

perty("Instance", yangyang);

perty("Database", "");

perty("User", user);

perty("Password", pwd);

perty("Version", version);

IWorkspaceFactory factory = new SdeWorkspaceFactoryClass();

IWorkspace workspace = (propSet, 0);

return workspace;

}

通过上述代码打开了SDE的工作空间,接下来要做的就是获取要编辑的FeatureClass。写一个函数,通

FeatureClass的别名和所在的Dataset返回FeatureClass。做法是先遍历所有的DataSet,找到符

合要求的Dataset之后遍历里面的要素,返回与参与别名一致的FeatureClass(顺便说一下,

FeatureClass在没有指定别名的时候默认与FeatureClass名称相同)

//查找指定要素

public IFeatureClass FindClassByName(IWorkspace ws, string className, string dsName)

{

IEnumDataset enumDs;

if (dsName != "")

{

enumDs = _Datasets(FeatureDataset);

IFeatureDataset featureDs = () as IFeatureDataset;

while (featureDs != null)

{

if (e == dsName)

{

return GetFcFromDataset(featureDs, className);

}

featureDs = () as IFeatureDataset;

}

}

else

{

enumDs = _Datasets(FeatureClass);

return GetFcFromEnumDataset(enumDs,className);

}

return null;

}

//在数据集中查找要素类

private IFeatureClass GetFcFromDataset(IFeatureDataset featDs, string className)

{

IFeatureClass featClass;

IFeatureClassContainer fcContainer = featDs as IFeatureClassContainer;

for (int i = 0; i < fcContainer.ClassCount; i++)

{

{

IWorkspace ws = FindWsByDefault();

IFeatureClass featClass = FindClassByName(ws, className, datasetName);

return featClass;

}

特别需要留意的是最后一个函数FindClassByName(,,先是打开SDE的工作空间,在这个工作空间

返回符合条件的要素集。通过这样的指向才能对SDEFeatureClass进行写入和删除的操作。可以把上

述代码写成一个静态类,这样就可以很方便的通过数据集名称和要数集别名指向要编辑的FeatureClass

了。

值得一提的是,很多新手都没有养成这种良好的习惯,就是先打开工作空间再进行数据的编辑 ,即便是使

shp文件或是MDB数据。他们习惯性的使用MapControl去加载MXD文件,然后在MapControl

_layer(index)IFeatureLayer

IFeatureClass进行操作。

事实上,MXD已经不用开发者写一句加载图层的代码就完成了对图层的加载,确实比较方便。但是它有很

多看不见的操作没有表现出来,加载完数据之后就把工作空间给自动关闭了。对于shp文件和MDB数据,

通过读取地图控件的图层是可以直接达到写入的目的,但一旦有用户进行操作该图层文件就会被锁死,这

就是不支持版本技术的表现。而SDE数据由于存在版本(原理不多说了),因此有需要去确保数据的安全

性和一致性,必须使用工作空间的形式去打开。如果用读取MapControl图层的方法去获取FeatureClass

实际上获取的是一个没有打开的编辑操作的FeatureClassESRI的帮助文档里面我们不难发现它是只

读的,就像在ArcMap里面没有用Editor执行startEdit一样。

2. 编辑SDE数据

利用上述的方法获取了FeatureClass后就可以用常规的方式对其进行编辑,如delete()和

CreateFeature(),或是更改属性值。但是仍然会出现无法编辑数据的现象,这种现象通常提示

没有足够的授权去编辑数据,这就涉及到AESDE数据编辑的授权,也就是gdbedite的授权

(主要是在AE9.2里面)

关于GDBEdite的授权,懒羊羊已经在之前发过一份比较完整的文档,但还是在这里再归纳一下。

ArcEngine9.2在用户许可上做了很大的改动,应用程序是强制初始化许可,也就是说必须使用

LicenseControlAO接口初始化许可,否则应用程序无法启动。Engine9.1未采取强制初始

化许可策略,而是应用程序创建时就初始化标准Engine许可。在一般情况下,我们会用将

LicenseControl拖放到主窗体上完成初始化。但当Engine程序需要使用ArcGIS Engine

Enterprise Geodatabase(以下简称GDB Update)许可的时候,我们就往往会由于意识不到

应该使用该许可,以及无法正确的初始化该许可而陷入麻烦。

对于许可这东西,首先要学会看软件产品的购货单。下表是一份关于ArcEngine9.2的购货单。

下面对GDB update许可进行讨论

1 什么情况下需要GDB Update许可

当需要对SDE里数据进行编辑时,以及需要在SDEPersonal Geodatabase中创建复杂ArcGIS

象时,需要使用GDB Update许可。

SDE里的数据编辑,很好理解,大致就是进行数据插入,删除,更新;对表添加、删除和修改,表结构

的变化(添加、删除列)等,因为这些动作都会造成后台数据库的写操作。

对于Personal Geodatabase进行简单数据对象和编辑,包括创建、删除和修改普通表都是不需要GDB

Update许可的,但对于复杂的Geodatabse对象的创建、删除和修改,则需要GDB Update许可,其

中复杂的Geodatabse对象包括几何网络,网络分析模型,拓扑,关系类。这也是为什么往往有写好了一

个创建几何网络或拓扑的程序后,执行起来会被报需要Geodatabase Update许可的错。

2 怎样初始化GDB Update许可

当我们意识到需要使用EngineGDB Update许可时,怎样才能将它正确的初始化呢?Engine给我们

提供了两种初始化许可的方法:

1 使用LicenseControl控件。将该控件拖放到主窗体之上,勾选适当的许可,并确保程序启动该

窗体可加载,就可以完成许可初始化。如下图:

2 使用lize方法加入适当的参数进行初始化

下面是C#的代码

private IAoInitialize m_AoInitialize = new AoInitializeClass();

private void Form1_Load(object sender, EventArgs e)

{ m_lize(censeProductCodeE

ngineGeoDB);

}

在窗体加载的时候初始化GDB许可。

当然,对于一个健壮的程序而言,我们还需要在初始化之前先判断将被初始化的许可是否可用,应先使用

IsProductCodeAvailable方法进行判断,需要初始化扩展模块的许可,可使用CheckOutExtension

法。 下面为许可的检测代码

private IAoInitialize m_AoInitialize = new AoInitializeClass();

private bool CheckLicenses()

{

//Create a new AoInitialize object

if (m_AoInitialize == null)

{

("Unable to initialize. This

application cannot run!");

return false;

}

//Determine if the product is available

esriLicenseStatus licenseStatus =

(esriLicenseStatus)m_uctCodeAvailable(cen

seProductCodeEngine);

if (licenseStatus == censeAvailable)

{

licenseStatus =

Engine);

if (licenseStatus != censeCheckedOut)

{

("The initialization failed. This

application cannot run!");

return false;

}

}

else

{

("The ArcGIS Engine product is

unavailable. This application cannot run!");

return false;

}

return true;

}

private void ReleaseLicenses()

{

(esriLicenseStatus)m_lize(censeProductCode

//Release COM objects and shutdown

wn();

m_wn();

}

private void FormMain_Load(object sender, EventArgs e)

{

if (CheckLicenses() == false) ();

}

private void FormMain_FormClosing(object sender, FormClosingEventArgs e)

{

ReleaseLicenses();

}

利用代码进行初始化适用于制作一些没有窗体的后台程序(没有窗体就不能通过LicenseControl进行许

可初始化,但要调用EngineGDB Update功能就必须通过它提供的初始化接口进行初始化,否则

Engine只能实现普通标准的功能)

3 初始化过程中容易犯的错误

初始化许可的一条重要原则就是一个程序只能初始化许可一次,已经初始化许可的程序一旦运行就无法再

修改其初始化的许可,即程序运行期间无法修改其使用的许可。

1 LicenseControlIAoInitialize接口两种初始化方法,一个应用程序中只能使用一种方法,如果两

种一起使用,哪一个说得算就不一定了。如果这两种方式同时使用,且两种初始化的许可级别一样时,

也许我们感觉不到什么不对,但当我们需要修改初始化许可级别,而又只改了一种初始化方法却忘记了另

一种,根据重要原则可知,这次修改初始化很可能无法生效。

2LicenseControl中多选许可是没有意义的,第一个被勾选的许可生效。如下图:

Engine

LicneseControl从操作上可以让用户多选许可,但并不代表它会将您勾选的许可全部签出。另

外,这些许可都是有对应和包含关系的。其中ArcGIS EngineArcView是对应的,ArcGIS

Engine Enterprise GeodatabaseArcEditor是对应的;ArcGIS Engine Enterprise

Geodatabase是包含ArcGIS Engine许可的。当我们需要GDB Update许可的时候,仅仅

需要勾选ArcGIS Engine Enterprise Geodatabase即可,为了保险起见勾选上其他许可

反而会弄巧成拙。

使用IAoInitialize接口进行初始化,Initialize方法只能调用一次,多余的调用是不会生效的,

道理就像上面LicenseControl勾选了多个许可一样。

说了那么多,希望新手们有所收获吧。同时也要向船长大哥说声对不起,因为之前有点忙,所以

没能如期的整理出来,恳请原谅。