深入FDO----資料維護

mapguide_inside發表於2009-11-29

 

本節將介紹如何用FDO API進行資料維護,資料維護相關的主要操作如下:

l  插入(Inserting

l  更新(Updating

l  刪除(Deleting

l  事務(Transactions

l  加鎖(Locking

1.1.1        屬性值

在執行插入和更新操作之前,往往需要為插入和更新的要素建立屬性值。FDO使用類FdoPropertyValue表示屬性值,建立一個屬性值需要如下兩個引數:

l  屬性名稱

l  值:值的型別必須和屬性型別匹配

值可以分為資料型別值和幾何型別值,資料型別值用來描述資料型別屬性值,幾何型別值用於描述幾何屬性的值,它們的類圖如93所示。

1.1.1.1  建立資料屬性值

FDO支援的資料型別有BooleanByteDateTimeDecimalDoubleInt16Int32Int64Single(單精度浮點數)、StringBLOB(二進位制大資料物件)、CLOB(字元大資料物件)。建立一個資料型別的值可以通過如下兩種方式之一:

1)  使用FdoDataValue,例如:Fdo

2)  使用FdoDataValue的子類

如下的程式碼展示瞭如何建立一個Decimal型別資料值,以及Decimal型別屬性值。

FdoPtr<FdoDataValue> sampleDataValue =

FdoDataValue::Create(100.0, FdoDataType_Decimal);

FdoPtr<FdoPropertyValue> sampleDataPropertyValue =

FdoPropertyValue::Create("Area", value);

FdoPtr<FdoDataValue> sampleDataValue = FdoDecimalValue::Create(100.0);

FdoPtr<FdoPropertyValue> sampleDataPropertyValue =

FdoPropertyValue::Create("Area", value);

 

Class Diagram

94 FDO值型別的類圖

1.1.1.2  建立幾何屬性值

幾何屬性值物件包含著一個用位元組陣列描述的幾何物件。一個幾何物件可以是簡單的,如,點;也可以是複雜的,如,多邊形。在幾何物件比較複雜的情況下,會建立多個幾何物件並將它們合併到一個幾何物件,最後把目標幾何物件轉化成位元組陣列從而得到幾何型別物件。

建立幾何屬性值物件的步驟如下:

1)  呼叫靜態的Create()方法來建立FdoGeometryValue型別的幾何資料物件。

2)  呼叫靜態的GetInstance()方法建立一個FdoAgfGeometryFactory型別的幾何工廠物件,該工廠是用來建立幾何型別物件的。

3)  呼叫相應的Create<geometry>()方法來建立所需的幾何物件。

4)  用幾何工廠將目標幾何物件轉換成位元組陣列。

5)  將自己陣列合併到幾何屬性物件中。

FdoPtr<FdoGeometryValue> sampleGeometryValue = FdoGeometryValue::Create();

// 建立一個用來建立幾何物件的幾何工廠

FdoPtr<FdoFgfGeometryFactory> sampleGeometryFactory =

FdoFgfGeometryFactory::GetInstance();

// 定義多邊形的外部邊界

FdoInt32 numOrdinates = 10;

double ordinates[] =

{52.0, 18.0, 66.0, 23.0, 73.0, 9.0, 48.0, 6.0, 52.0, 18.0};

FdoPtr<FdoILinearRing> exteriorRing =

sampleGeometryFactory->CreateLinearRing(FdoDimensionality_XY,

numOrdinates, ordinates);

// 建立多邊形

FdoPtr<FdoIPolygon> polygon =

sampleGeometryFactory->CreatePolygon(exteriorRing, NULL);

// 將多邊形轉換成位元組陣列,然後設定幾何型別的值

FdoPtr<FdoByteArray> geometryByteArray = sampleGeometryFactory->GetAgf(polygon);

sampleGeometryValue->SetGeometry(geometryByteArray);

// FdoGeometryValue型別的新增到幾何屬性中

FdoPtr<FdoPropertyValue> sampleGeometryPropertyValue =

FdoPropertyValue::Create(L"SampleGeometryProperty", sampleGeometryValue);

1.1.2        插入操作

現在我們可以建立要素資料物件,也就是要素類的例項,並把他們插入到Data Store中。為了便於理解,我們可以認為一個FDO的類就是關聯式資料庫中的一個表,而類的屬性相當於表的列,於是新增屬性值就是向表中新增一行了。

插入操作包含以下步驟:

1)  建立FdoIInsert型別的插入命令物件,該物件可被多次插入操作重用。

2)  通過呼叫SetFeatureClassName(<className>)方法來設定需要插入屬性值的要素類。

3)  呼叫插入命令物件的GetPropertyValues()方法來得到FdoPropertyValueCollection型別的屬性值集合。在使用插入命令物件插入屬性值之前,必須先把各屬性值新增到該屬性集合中。

4)  建立FdoDataValue型別的資料值或FdoGeometryValue型別的幾何值。建立資料值直接呼叫靜態的Create()方法,傳入字串或整型值即可;建立幾何型別值請參考幾何屬性值

5)  呼叫靜態Create()方法並傳入資料型別或集合型別物件來建立FdoPropertyValue型別的屬性值物件。

6)  將屬性值物件加入到第三步中得到的屬性值集合中。

7)  呼叫Execute()方法執行插入命令。

在前面的章節我們建立了一個要素模式並給它新增了一個要素類,該要素類有三個屬性:一個整型資料屬性,一個字串型別屬性以及一個幾何屬性。而後,我們把該要素模式應用到了Data Store中。有了模式和要素類,我們就可以建立要素類的物件並把他們插入到Data Store中了。

以下示例程式碼展示瞭如何插入一個整型、字串以及一個幾何型別屬性值。

// 建立插入命令

FdoPtr<FdoIInsert> sampleInsert = (FdoIInsert *)

connection->CreateCommand(FdoCommandType_Insert);

// 插入操作返回的索引值

FdoInt32 valueCollectionIndex = 0;

// 為插入命令指定目標要素類

// 傳入一個完整的要素類名,其格式為“<schemaName>:<className>

sampleInsert-> SetFeatureClassName(L"SampleFeatureSchema:SampleFeatureClass");

// 得到屬性值集合,新建的屬性將插入到該集合中

FdoPtr<FdoPropertyValueCollection> samplePropertyValues =

sampleInsert->GetPropertyValues();

// 為主鍵屬性建立一個FdoDataValue型別的值

FdoPtr<FdoDataValue> sampleIdentityDataValue = FdoDataValue::Create(101);

// FdoDataValue新增到主鍵屬性中

FdoPtr<FdoPropertyValue> sampleIdentityPropertyValue =

FdoPropertyValue::Create(L"SampleIdentityDataProperty", sampleIdentityDataValue);

// 將主鍵屬性值新增到屬性值集合

valueCollectionIndex = samplePropertyValues->Add(sampleIdentityPropertyValue);

// 為屬性“name”建立一個FdoDataValue型別的值

FdoPtr<FdoDataValue> sampleNameDataValue = FdoDataValue::Create(L"Blue Lake");

// FdoDataValue型別的值新增到name屬性

FdoPtr<FdoPropertyValue> sampleNamePropertyValue =

FdoPropertyValue::Create(L"SampleNameDataProperty", sampleNameDataValue);

// 將“name屬性值新增到屬性值集合

valueCollectionIndex = samplePropertyValues->Add(sampleNamePropertyValue);

// 為幾何屬性建立一個FdoGeometryValue型別的值

// 該多邊形描繪了一個帶有一個小島的湖

// 湖的外邊界是用Linear Ring來描述的,湖的外邊界也是多邊形的外邊界

// 島的邊界也是用Linear Ring來描述的,島的外邊界是多邊形的內部邊界

FdoPtr<FdoGeometryValue> sampleGeometryValue = FdoGeometryValue::Create();

// 建立一個用來建立幾何物件的幾何工廠

FdoPtr<FdoFgfGeometryFactory> sampleGeometryFactory =

FdoFgfGeometryFactory::GetInstance();

// 定義多邊形的外部邊界,也就是“Blue Lake的外邊界

FdoInt32 numBlueLakeShorelineOrdinates = 10;

double blueLakeExteriorRingOrdinates[] =

{52.0, 18.0, 66.0, 23.0, 73.0, 9.0, 48.0, 6.0, 52.0, 18.0};

FdoPtr<FdoILinearRing> exteriorRingBlueLake =

sampleGeometryFactory->CreateLinearRing(FdoDimensionality_XY, umBlueLakeShorelineOrdinates, blueLakeExteriorRingOrdinates);

// 定義“Blue Lake內部小島“Goose的邊界

FdoInt32 numGooseIslandShorelineOrdinates = 10;

double gooseIslandLinearRingOrdinates[] =

{59.0, 18.0, 67.0, 18.0, 67.0, 13.0, 59.0, 13.0, 59.0, 18.0};

FdoPtr<FdoILinearRing> linearRingGooseIsland =

sampleGeometryFactory->CreateLinearRing(FdoDimensionality_XY, umGooseIslandShorelineOrdinates, gooseIslandLinearRingOrdinates);

// 將“Goose島的邊界加入到內部邊界集合中

FdoPtr<FdoLinearRingCollection> interiorRingsBlueLake =

FdoLinearRingCollection::Create();

interiorRingsBlueLake->Add(linearRingGooseIsland);

// 建立“Blue Lake多邊形

FdoPtr<FdoIPolygon> blueLake =

sampleGeometryFactory->CreatePolygon(exteriorRingBlueLake, interiorRingsBlueLake);

// 將“Blue Lake”多邊形轉換成位元組陣列,然後設定幾何型別的值

FdoPtr<FdoByteArray> geometryByteArray = sampleGeometryFactory->GetAgf(blueLake);

sampleGeometryValue->SetGeometry(geometryByteArray);

// FdoGeometryValue型別的“Blue Lake”新增到幾何屬性中

FdoPtr<FdoPropertyValue> sampleGeometryPropertyValue =

FdoPropertyValue::Create(L"SampleGeometryProperty", sampleGeometryValue);

// 將幾何屬性值新增到屬性值集合中

valueCollectionIndex = samplePropertyValues->Add(sampleGeometryPropertyValue);

// 執行插入操作,插入命令返回一個FdoIFeatureReader

FdoPtr<FdoIFeatureReader sampleFeatureReader = sampleInsert->Execute();

1.1.3        更新屬性值

插入屬性之後也可以對屬性進行修改。更新操作指的是找出要素類(相當於“表”)、要素(相當於“行”)以及要修改的屬性(相當於“行的某一列”),然後用新的屬性值取代舊的屬性值。

首先,要建立一個FdoIUpdate命令物件,呼叫該物件的SetFeatureClassName()方法來查詢相應的要素類。

然後,建立一個過濾器來查詢需要更新的要素物件,呼叫命令物件的SetFilter()方法可以設定過濾條件。

前面的示例中,要素類SampleFeatureClass包含了一個名為“SampleIdentityDataProperty”的資料屬性,它是一個Int32型別的主鍵屬性,也就是說它的值可以唯一確定一個要素,即一 “行”。我們使用主鍵屬性名來設定過濾器,該關鍵屬性的值為101,所以過濾器應該為“(SampleIdentityDataProperty = 101)”。

最後,建立一個新的屬性值,將其新增到更新命令並執行。

以下示例展示瞭如何更新一個屬性值。

// 建立更新命令

FdoPtr<FdoIUpdate> sampleUpdate =

(FdoIUpdate *)connection->CreateCommand(FdoCommandType_Update);

// 為更新命令指定目標要素類

// 傳入一個完整的要素類名,其格式為“<schemaName>:<className>

sampleUpdate-> SetFeatureClassName(L"SampleFeatureSchema:SampleFeatureClass");

// 設定過濾條件來鎖定目標集合

sampleUpdate->SetFilter(L"( SampleIdentityDataProperty = 101 )");

// 得到屬性集合,用以向更新命令中新增屬性

// 這裡我們將重用插入操作裡用到的samplePropertyValues物件

samplePropertyValues = sampleUpdate->GetPropertyValues();

// name屬性建立一個FdoDataValue型別的物件

FdoPtr<FdoDataValue> sampleNameDataValue = FdoDataValue::Create(L"Green Lake");

// 設定屬性名以及對應的值

sampleNamePropertyValue->SetName(L"SampleNameDataProperty");

sampleNamePropertyValue->SetValue(sampleNameDataValue);

// 新增name屬性物件到更新命令的屬性集合中

samplePropertyValues->Add(sampleNamePropertyValue);

// 執行命令,返回值為更新命令所更新的要素總數

FdoInt32 numUpdated = sampleUpdate->Execute();

1.1.4        刪除要素

除了插入和更新操作,我們還可以執行刪除操作。刪除操作是針對要素的,也就是相當於刪除資料庫表中的某一行。

首先,需要建立一個FdoIDelete命令物件,呼叫物件的SetFeatureClassName()方法來找到相應的要素類。然後,建立一個過濾器來定位所要刪除的要素,此處的過濾和前面講到的完全一樣。最後,執行刪除命令。

以下示例展示瞭如何刪除一個要素。

// 建立刪除命令

FdoPtr<FdoIDelete> sampleDelete =

(FdoIDelete *)connection->CreateCommand(FdoCommandType_Delete);

// 為刪除命令指定目標要素類

// 傳入一個完整的要素類名,其格式為“<schemaName>:<className>

sampleDelete->SetFeatureClassName(L"SampleFeatureSchema:SampleFeatureClass");

// 設定過濾條件來鎖定目標集合

sampleDelete->SetFilter(L"( SampleIdentityDataProperty = 101 )");

// 執行命令,返回值為刪除命令所刪除的要素總數

FdoInt32 numDeleted = sampleDelete->Execute();

1.1.5        管理事務

9.1.2.2中,我們介紹過事務的概念。一個事務是指由一系列資料操作組成的一個完整的邏輯過程,它具原子性、一致性、隔離性和永續性的特點。

FDO中事務的概念和RDBMS中事務的概念是基本相同的,和RDBMS中的事務一樣,FDO的事務也是關聯與一個連線。呼叫FdoIConnection::StartTransaction()可以啟動一個事務,它會返回一個FDO事務FdoTransaction物件,呼叫FdoITransaction::Commit()可以提交一個事務,在啟動事務後針對Data Store所做的所有修改寫入資料來源中,呼叫FdoITransaction::Rollback()可以回滾一個事務,在啟動事務後針對Data Store所做的所有修改會全部撤銷,就像從來沒有做過這些修改一樣。

FdoPtr<FdoTransaction> transaction;

FdoPtr<FdoICommand> command;

try {

// 啟動事務

    transaction = connection->BeginTransaction();

    ......

    command->SetTransaction(transaction);

    ......

    transaction->Commit();

}

catch (FdoException* e) {

    e->Release();

    transaction->Rollback();

}

不過,FDO不支援巢狀事務,這就意味著如果當前連線啟動了一個事務,那麼在這個事務提交或回滾之前,使用者不可以再啟動一個新的事務。

需要注意的是事務和長事務不是兩個相同的概念,在9.9中我們會介紹長事務。

 

相關文章