sde是esri开发的一个空间数据引擎,能够利用文件数据库良好的管理优势去管理数据的图形和属性。accessdatabase
与后来的 filegeodatabase同样也能够很好的管理数据,但是与sde数据库最大差别是它们不支持多用户同时编辑,也就是sde的版本技术。虽然大家都知道这些,但是懒羊羊还是要顺便提一下。
很多人第一次接触sde数据的时候思想可能还停留在对shp文件或是mdb文件的操作上面。事实上它们大部分的操作时一致的,但接入的方式有所不同。由于sde多了一个版本的控制,所以在数据的载入与打开featureclass的时候有很大的差别。下面开始转入正题,讲述一下如何对sde数据进行操作。
1.打开sde数据。
sde数据一定要使用工作空间工厂去初始化工作空间,在工作空间打开featureclass,这是最常规的操作。下面通过一段c#代码连接sde,打开并返回一个iworkspace。
public iworkspace findwsbydefault()
{
ipropertyset propset = new propertysetclass();
propset.setproperty("server", lan);
propset.setproperty("instance", yangyang);
propset.setproperty("database", "");
propset.setproperty("user", user);
propset.setproperty("password", pwd);
propset.setproperty("version", version);
iworkspacefactory factory = new sdeworkspacefactoryclass();
iworkspace workspace = factory.open(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 = ws.get_datasets(esridatasettype.esridtfeaturedataset);
ifeaturedataset featureds = enumds.next() as ifeaturedataset;
while (featureds != null)
{
if (featureds.name == dsname)
{
return getfcfromdataset(featureds, classname);
}
featureds = enumds.next() as ifeaturedataset;
}
}
else
enumds = ws.get_datasets(esridatasettype.esridtfeatureclass);
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++)
featclass = fccontainer.get_class(i);
if (featclass.aliasname == classname)
return featclass;
//在要素类集合中查找要素类
private ifeatureclass getfcfromenumdataset(ienumdataset enumds, string classname)
ifeatureclass featclass = enumds.next() as ifeatureclass;
while (featclass != null)
featclass = enumds.next() as ifeatureclass;
//通过要素类名和数据集名在指定的工作空间中寻找要素类
public ifeatureclass findclassbyname(string classname, string datasetname)
iworkspace ws = findwsbydefault();
ifeatureclass featclass = findclassbyname(ws, classname, datasetname);
return featclass;
特别需要留意的是最后一个函数findclassbyname(,),先是打开sde的工作空间,在这个工作空间返回符合条件的要素集。通过这样的指向才能对sde的featureclass进行写入和删除的操作。可以把上述代码写成一个静态类,这样就可以很方便的通过数据集名称和要数集别名指向要编辑的featureclass了。
值得一提的是,很多新手都没有养成这种良好的习惯,就是先打开工作空间再进行数据的编辑,即便是使用shp文件或是mdb数据。他们习惯性的使用mapcontrol去加载mxd文件,然后在mapcontrol通过mapcontrol.get_layer(index)的方法去获取图层,然后将其转为ifeaturelayer或是ifeatureclass进行操作。
事实上,mxd已经不用开发者写一句加载图层的代码就完成了对图层的加载,确实比较方便。但是它有很多看不见的操作没有表现出来,加载完数据之后就把工作空间给自动关闭了。对于shp文件和mdb数据,通过读取地图控件的图层是可以直接达到写入的目的,但一旦有用户进行操作该图层文件就会被锁死,这就是不支持版本技术的表现。而sde数据由于存在版本(原理不多说了),因此有需要去确保数据的安全性和一致性,必须使用工作空间的形式去打开。如果用读取mapcontrol图层的方法去获取featureclass,实际上获取的是一个没有打开的编辑操作的featureclass,在esri的帮助文档里面我们不难发现它是只读的,就像在arcmap里面没有用editor执行startedit一样。
2. 编辑sde数据
利用上述的方法获取了featureclass后就可以用常规的方式对其进行编辑,如delete()和createfeature(),或是更改属性值。但是仍然会出现无法编辑数据的现象,这种现象通常提示没有足够的授权去编辑数据,这就涉及到ae对sde数据编辑的授权,也就是gdbedite的授权(主要是在ae9.2里面)。
关于gdbedite的授权,懒羊羊已经在之前发过一份比较完整的文档,但还是在这里再归纳一下。
arcengine9.2在用户许可上做了很大的改动,应用程序是强制初始化许可,也就是说必须使用licensecontrol或ao接口初始化许可,否则应用程序无法启动。engine9.1未采取强制初始化许可策略,而是应用程序创建时就初始化标准engine许可。在一般情况下,我们会用将licensecontrol拖放到主窗体上完成初始化。但当engine程序需要使用arcgis engine enterprise geodatabase(以下简称gdb update)许可的时候,我们就往往会由于意识不到应该使用该许可,以及无法正确的初始化该许可而陷入麻烦。
对于许可这东西,首先要学会看软件产品的购货单。下表是一份关于arcengine9.2的购货单。

下面对gdb update许可进行讨论
(1)什么情况下需要gdb update许可
当需要对sde里数据进行编辑时,以及需要在sde和personal geodatabase中创建复杂arcgis对象时,需要使用gdb update许可。
对sde里的数据编辑,很好理解,大致就是进行数据插入,删除,更新;对表添加、删除和修改,表结构的变化(添加、删除列)等,因为这些动作都会造成后台数据库的写操作。
对于personal geodatabase,进行简单数据对象和编辑,包括创建、删除和修改普通表都是不需要gdb update许可的,但对于复杂的geodatabse对象的创建、删除和修改,则需要gdb update许可,其中复杂的geodatabse对象包括几何网络,网络分析模型,拓扑,关系类。这也是为什么往往有写好了一个创建几何网络或拓扑的程序后,执行起来会被报“需要geodatabase update许可”的错。
(2) 怎样初始化gdb update许可
当我们意识到需要使用engine的gdb update许可时,怎样才能将它正确的初始化呢?engine给我们提供了两种初始化许可的方法:
1)使用licensecontrol控件。将该控件拖放到主窗体之上,勾选适当的许可,并确保程序启动该窗体可加载,就可以完成许可初始化。如下图:
2)使用iaoinitialize.initialize方法加入适当的参数进行初始化
下面是c#的代码
private iaoinitialize m_aoinitialize = new aoinitializeclass();
private void form1_load(object sender, eventargs e)
{ m_aoinitialize.initialize(esrilicenseproductcode.esrilicenseproductcodeenginegeodb);
}
在窗体加载的时候初始化gdb许可。
当然,对于一个健壮的程序而言,我们还需要在初始化之前先判断将被初始化的许可是否可用,应先使用isproductcodeavailable方法进行判断,需要初始化扩展模块的许可,可使用checkoutextension方法。下面为许可的检测代码
private bool checklicenses()
//create a new aoinitialize object
if (m_aoinitialize == null)
system.windows.forms.messagebox.show("unable to initialize. this application cannot run!");
return false;
//determine if the product is available
esrilicensestatus licensestatus = (esrilicensestatus)m_aoinitialize.isproductcodeavailable(esrilicenseproductcode.esrilicenseproductcodeengine);
if (licensestatus == esrilicensestatus.esrilicenseavailable)
licensestatus = (esrilicensestatus)m_aoinitialize.initialize(esrilicenseproductcode.esrilicenseproductcodeengine);
if (licensestatus != esrilicensestatus.esrilicensecheckedout)
system.windows.forms.messagebox.show("the initialization failed. this application cannot run!");
return false;
system.windows.forms.messagebox.show("the arcgis engine product is unavailable. this application cannot run!");
return true;
private void releaselicenses()
//release com objects and shutdown
esri.arcgis.utility.comsupport.aouninitialize.shutdown();
m_aoinitialize.shutdown();
private void formmain_load(object sender, eventargs e)
if (checklicenses() == false) this.close();
private void formmain_formclosing(object sender, formclosingeventargs e)
releaselicenses();
}
利用代码进行初始化适用于制作一些没有窗体的后台程序(没有窗体就不能通过licensecontrol进行许可初始化,但要调用engine的gdb update功能就必须通过它提供的初始化接口进行初始化,否则engine只能实现普通标准的功能)
(3)初始化过程中容易犯的错误
初始化许可的一条重要原则就是一个程序只能初始化许可一次,已经初始化许可的程序一旦运行就无法再修改其初始化的许可,即程序运行期间无法修改其使用的许可。
1) licensecontrol和iaoinitialize接口两种初始化方法,一个应用程序中只能使用一种方法,如果两种一起使用,哪一个“说得算”就不一定了。如果这两种方式同时使用,且两种初始化的许可级别一样时,也许我们感觉不到什么不对,但当我们需要修改初始化许可级别,而又只改了一种初始化方法却忘记了另一种,根据“重要原则”可知,这次修改初始化很可能无法生效。
2)licensecontrol中多选许可是没有意义的,第一个被勾选的许可生效。如下图:
这种情况下,实际上该应用程序初始化的是engine标准许可,而不是其他。虽然licnesecontrol从操作上可以让用户多选许可,但并不代表它会将您勾选的许可全部签出。另外,这些许可都是有对应和包含关系的。其中arcgis
engine与arcview是对应的,arcgis engine enterprise geodatabase与arceditor是对应的;arcgis
engine enterprise geodatabase是包含arcgis engine许可的。当我们需要gdb update许可的时候,仅仅需要勾选arcgis
engine enterprise geodatabase即可,为了“保险起见”勾选上其他许可反而会弄巧成拙。
使用iaoinitialize接口进行初始化,initialize方法只能调用一次,多余的调用是不会生效的,道理就像上面licensecontrol勾选了多个许可一样。