如何编辑SDE数据(转自ESRI中国社区)
很多剛?cè)腴T的朋友對SDE數(shù)據(jù)并不太了解,接二連三的在社區(qū)里面發(fā)問,有時也得不到很好的解答,對此懶羊羊也深感同情。想到剛?cè)腴T時的痛苦,懶羊羊決定抽寫時間出來詳細(xì)的講述如何去編輯SDE數(shù)據(jù),希望可以跟廣大新手一同成長,度過入門的艱難時期。如有錯誤或表述含糊的地方,還請眾高手指正。
SDE矢ESRI開發(fā)的一個空間數(shù)據(jù)引擎,能夠利用文件數(shù)據(jù)庫良好的管理優(yōu)勢去管理數(shù)據(jù)的圖形和屬性。AccessDatabase 與后來的 FileGeoDataBase同樣也能夠很好的管理數(shù)據(jù),但是與SDE數(shù)據(jù)庫最大差別是它們不支持多用戶同時編輯,也就是SDE的版本技術(shù)。雖然大家都知道這些,但是懶羊羊還是要順便提一下。
很多人第一次接觸SDE數(shù)據(jù)的時候思想可能還停留在對shp文件或是MDB文件的操作上面。事實上它們大部分的操作時一致的,但接入的方式有所不同。由于SDE多了一個版本的控制,所以在數(shù)據(jù)的載入與打開FeatureClass的時候有很大的差別。下面開始轉(zhuǎn)入正題,講述一下如何對SDE數(shù)據(jù)進(jìn)行操作。
1.打開SDE數(shù)據(jù)。
SDE數(shù)據(jù)一定要使用工作空間工廠去初始化工作空間,在工作空間打開FeatureClass,這是最常規(guī)的操作。下面通過一段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。寫一個函數(shù),通過FeatureClass的別名和所在的 Dataset返回FeatureClass。做法是先遍歷所有的DataSet,找到符合要求的Dataset之后遍歷里面的要素,返回與參與別名一致的FeatureClass(順便說一下,FeatureClass在沒有指定別名的時候默認(rèn)與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;
}
//在數(shù)據(jù)集中查找要素類
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;
}
}
return null;
}
//在要素類集合中查找要素類
private IFeatureClass GetFcFromEnumDataset(IEnumDataset enumDs, string className)
{
IFeatureClass featClass = enumDs.Next() as IFeatureClass;
while (featClass != null)
{
if (featClass.AliasName == className)
{
return featClass;
}
featClass = enumDs.Next() as IFeatureClass;
}
return null;
}
//通過要素類名和數(shù)據(jù)集名在指定的工作空間中尋找要素類
public IFeatureClass FindClassByName(string className, string datasetName)
{
IWorkspace ws = FindWsByDefault();
IFeatureClass featClass = FindClassByName(ws, className, datasetName);
return featClass;
}
特別需要留意的是最后一個函數(shù)FindClassByName(,),先是打開SDE的工作空間,在這個工作空間返回符合條件的要素集。通過這樣的指向才能對SDE的FeatureClass進(jìn)行寫入和刪除的操作。可以把上述代碼寫成一個靜態(tài)類,這樣就可以很方便的通過數(shù)據(jù)集名稱和要數(shù)集別名指向要編輯的 FeatureClass了。
值得一提的是,很多新手都沒有養(yǎng)成這種良好的習(xí)慣,就是先打開工作空間再進(jìn)行數(shù)據(jù)的編輯,即便是使用shp文件或是MDB數(shù)據(jù)。他們習(xí)慣性的使用 MapControl去加載MXD文件,然后在MapControl通過MapControl.get_layer(index)的方法去獲取圖層,然后將其轉(zhuǎn)為IFeatureLayer或是IFeatureClass進(jìn)行操作。
事實上,MXD已經(jīng)不用開發(fā)者寫一句加載圖層的代碼就完成了對圖層的加載,確實比較方便。但是它有很多看不見的操作沒有表現(xiàn)出來,加載完數(shù)據(jù)之后就把工作空間給自動關(guān)閉了。對于shp文件和MDB數(shù)據(jù),通過讀取地圖控件的圖層是可以直接達(dá)到寫入的目的,但一旦有用戶進(jìn)行操作該圖層文件就會被鎖死,這就是不支持版本技術(shù)的表現(xiàn)。而SDE數(shù)據(jù)由于存在版本(原理不多說了),因此有需要去確保數(shù)據(jù)的安全性和一致性,必須使用工作空間的形式去打開。如果用讀取 MapControl圖層的方法去獲取FeatureClass,實際上獲取的是一個沒有打開的編輯操作的FeatureClass,在ESRI的幫助文檔里面我們不難發(fā)現(xiàn)它是只讀的,就像在ArcMap里面沒有用Editor執(zhí)行startEdit一樣。
2. 編輯SDE數(shù)據(jù)
利用上述的方法獲取了FeatureClass后就可以用常規(guī)的方式對其進(jìn)行編輯,如delete()和CreateFeature(),或是更改屬性值。但是仍然會出現(xiàn)無法編輯數(shù)據(jù)的現(xiàn)象,這種現(xiàn)象通常提示沒有足夠的授權(quán)去編輯數(shù)據(jù),這就涉及到AE對SDE數(shù)據(jù)編輯的授權(quán),也就是gdbedite的授權(quán)(主要是在AE9.2里面)。
關(guān)于GDBEdite的授權(quán),懶羊羊已經(jīng)在之前發(fā)過一份比較完整的文檔,但還是在這里再歸納一下。
ArcEngine9.2在用戶許可上做了很大的改動,應(yīng)用程序是強(qiáng)制初始化許可,也就是說必須使用LicenseControl或AO接口初始化許可,否則應(yīng)用程序無法啟動。Engine9.1未采取強(qiáng)制初始化許可策略,而是應(yīng)用程序創(chuàng)建時就初始化標(biāo)準(zhǔn)Engine許可。在一般情況下,我們會用將 LicenseControl拖放到主窗體上完成初始化。但當(dāng)Engine程序需要使用ArcGIS Engine Enterprise Geodatabase(以下簡稱GDB Update)許可的時候,我們就往往會由于意識不到應(yīng)該使用該許可,以及無法正確的初始化該許可而陷入麻煩。
對于許可這東西,首先要學(xué)會看軟件產(chǎn)品的購貨單。下表是一份關(guān)于ArcEngine9.2的購貨單。
下面對GDB update許可進(jìn)行討論
(1)什么情況下需要GDB Update許可
當(dāng)需要對SDE里數(shù)據(jù)進(jìn)行編輯時,以及需要在SDE和Personal Geodatabase中創(chuàng)建復(fù)雜ArcGIS對象時,需要使用GDB Update許可。
對SDE里的數(shù)據(jù)編輯,很好理解,大致就是進(jìn)行數(shù)據(jù)插入,刪除,更新;對表添加、刪除和修改,表結(jié)構(gòu)的變化(添加、刪除列)等,因為這些動作都會造成后臺數(shù)據(jù)庫的寫操作。
對于Personal Geodatabase,進(jìn)行簡單數(shù)據(jù)對象和編輯,包括創(chuàng)建、刪除和修改普通表都是不需要GDB Update許可的,但對于復(fù)雜的Geodatabse對象的創(chuàng)建、刪除和修改,則需要GDB Update許可,其中復(fù)雜的Geodatabse對象包括幾何網(wǎng)絡(luò),網(wǎng)絡(luò)分析模型,拓?fù)?#xff0c;關(guān)系類。這也是為什么往往有寫好了一個創(chuàng)建幾何網(wǎng)絡(luò)或拓?fù)涞某绦蚝?#xff0c;執(zhí)行起來會被報“需要Geodatabase Update許可”的錯。
(2) 怎樣初始化GDB Update許可
當(dāng)我們意識到需要使用Engine的GDB Update許可時,怎樣才能將它正確的初始化呢?Engine給我們提供了兩種初始化許可的方法:
1)使用LicenseControl控件。將該控件拖放到主窗體之上,勾選適當(dāng)?shù)脑S可,并確保程序啟動該窗體可加載,就可以完成許可初始化。如下圖:
2)使用IAoInitialize.Initialize方法加入適當(dāng)?shù)膮?shù)進(jìn)行初始化
下面是C#的代碼
private IAoInitialize m_AoInitialize = new AoInitializeClass();
private void Form1_Load(object sender, EventArgs e)
{? m_AoInitialize.Initialize(esriLicenseProductCode.esriLicenseProductCodeEngineGeoDB);
}?
在窗體加載的時候初始化GDB許可。
當(dāng)然,對于一個健壯的程序而言,我們還需要在初始化之前先判斷將被初始化的許可是否可用,應(yīng)先使用IsProductCodeAvailable方法進(jìn)行判斷,需要初始化擴(kuò)展模塊的許可,可使用CheckOutExtension方法。下面為許可的檢測代碼
private IAoInitialize m_AoInitialize = new AoInitializeClass();
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;
}
}
else
{
System.Windows.Forms.MessageBox.Show("The ArcGIS Engine product is unavailable. This application cannot run!");
return false;
}
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();
}
利用代碼進(jìn)行初始化適用于制作一些沒有窗體的后臺程序(沒有窗體就不能通過LicenseControl進(jìn)行許可初始化,但要調(diào)用Engine的GDB Update功能就必須通過它提供的初始化接口進(jìn)行初始化,否則Engine只能實現(xiàn)普通標(biāo)準(zhǔn)的功能)
(3)初始化過程中容易犯的錯誤
初始化許可的一條重要原則就是一個程序只能初始化許可一次,已經(jīng)初始化許可的程序一旦運(yùn)行就無法再修改其初始化的許可,即程序運(yùn)行期間無法修改其使用的許可。
1) LicenseControl和IAoInitialize接口兩種初始化方法,一個應(yīng)用程序中只能使用一種方法,如果兩種一起使用,哪一個“說得算”就不一定了。如果這兩種方式同時使用,且兩種初始化的許可級別一樣時,也許我們感覺不到什么不對,但當(dāng)我們需要修改初始化許可級別,而又只改了一種初始化方法卻忘記了另一種,根據(jù)“重要原則”可知,這次修改初始化很可能無法生效。
2)LicenseControl中多選許可是沒有意義的,第一個被勾選的許可生效。如下圖:
這種情況下,實際上該應(yīng)用程序初始化的是Engine標(biāo)準(zhǔn)許可,而不是其他。雖然LicneseControl從操作上可以讓用戶多選許可,但并不代表它會將您勾選的許可全部簽出。另外,這些許可都是有對應(yīng)和包含關(guān)系的。其中ArcGIS Engine與ArcView是對應(yīng)的,ArcGIS Engine Enterprise Geodatabase與ArcEditor是對應(yīng)的;ArcGIS Engine Enterprise Geodatabase是包含ArcGIS Engine許可的。當(dāng)我們需要GDB Update許可的時候,僅僅需要勾選ArcGIS Engine Enterprise Geodatabase即可,為了“保險起見”勾選上其他許可反而會弄巧成拙。
使用IAoInitialize接口進(jìn)行初始化,Initialize方法只能調(diào)用一次,多余的調(diào)用是不會生效的,道理就像上面LicenseControl勾選了多個許可一樣。
說了那么多,希望新手們有所收獲吧。同時也要向船長大哥說聲對不起,因為之前有點忙,所以沒能如期的整理出來,懇請原諒。
總結(jié)
以上是生活随笔為你收集整理的如何编辑SDE数据(转自ESRI中国社区)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑卡顿,最先升级这个硬件,运行速度可快
- 下一篇: logisim优先编码器怎么用_变频电机