深入FDO----建立FDO连接

在访问数据源中的任何数据之前,首先需要建立一个对应的FDO Provider连接。本节中将介绍如何创建一个FDO Provider的连接。

1.1.1        数据源和Data Store

在创建一个FDO Provider连接之前,我们需要明白两个概念:数据源和Data Store。因为准确的来说,FDO的连接是针对Data Store的,而不是数据源。

在介绍FDO的基本概念时,我们提到Data Store表示包含零个或多个对象的集合。FDO连接是针对Data Store的,因为它是存储数据对象的地方。Data Store既可以保存在数据库中(如MySQL),也可以保存在文件(如SDF文件)。

Data Store和数据源可以是一对一或多对一的,即一个数据源包含一个或多个Data Store,这取决于FDO Provider的能力,例如:

l  对于OSGeo FDO Provider for ArcSDE的连接,在ArcSDE服务器使用Oracle数据库时,Data Store和数据源是一对一的。

l  对于OSGeo FDO Provider for MySQL的连接,Data Store和数据源是多对一的。

Data Store和数据源是多对一时,连接可以经过一步或两步完成,将介绍不同连接方式的具体细节。

1.1.2        注册Provider

在安装FDO SDK时,FDO会自动注册FDO SDK中包含的所有FDO Provider。如果你想添加一种FDO SDK中没有包含的FDO Provider,就需要自己来注册这种FDO Provider,例如企业版FDO中没有包含OSGeo FDO Provider for GDAL,如果要在FDO企业版中使用GDAL Provider,就需要自己来注册FDO Provider。注册FDO Provider的方式有如下两种方式:

1)  修改文件providers.xml

FDO的安装目录下有一个名称为“providers.xml”XML文件,它包含了所有已经注册的FDO Provider,例如修改此文件加入如下两个省略号中间的内容,就可以注册GDAL Provider

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>

<FeatureProviderRegistry>

  ......

<FeatureProvider>

    <Name>OSGeo.Gdal.3.4</Name>

    <DisplayName>OSGeo FDO Provider for GDAL</DisplayName>

    <Description>FDO Provider for GDAL</Description>

    <IsManaged>False</IsManaged>

    <Version>3.4.0.0</Version>

    <FeatureDataObjectsVersion>3.4.0.0</FeatureDataObjectsVersion>

    <LibraryPath>./GRFPProvider.dll</LibraryPath>

  </FeatureProvider>

  ......

</FeatureProviderRegistry>

新加XML片段中每个元素的解释如下:

l  NameProvider的唯一命名,该命名需遵循<公司名/组织名称>.<Provider>.<版本号>的命名规则,例如:“Autodesk.Oracle.3.0”“OSGeo.MySQL.3.0”

l  DisplayNameProvider显示给用户的名字,例如:“Autodesk FDO Provider for Oracle”“OSGeo FDO Provider for SDF”或者本地化的字符串。

l  DescriptionProvider的简要描述,例如:OSGeo FDO Provider for SDF的描述为“Read/write access to Autodesk's spatial database format, a file-based personal geodatabase that supports multiple features/attributes, spatial indexing, and file-locking.”

l  VersionProvider的版本号,版本号一般遵循以下命名规则:<主版本号>.<次版本号>.<Build>.<Build>,例如:3.0.0.0

l  FDOVersionProvider所在的FDO版本号,该版本号也遵循以下命名规则:<主版本号>.<次版本号>.<Build>.<Build>。例如:3.0.1.0

l  libraryPath:包含文件名在内的provider完整路径名,例如:<FDO SDK安装路径>/bin/FdoRdbms.dll.

l  isManaged:用来标志Provider是托管的(Managed).NET FDO Provider,还是非托管的(Unmanaged)C++ Provider

2)  编程方式

FDO APIProvider的注册和注销提供了接口,详情可参考文件Inc/Fdo/ClientServices/ProviderRegistry.h中的类FdoProviderRegistry

1.1.3        建立连接

1.1.3.1        获取Provider的名称

要创建到一个Provider的连接,必须知道这个Provider的完整名称,Provider的命名需遵循如下格式:<公司名/组织名称>.<Provider>.<版本号>,其中<公司名/组织名称><Provider>是不变的,只有<版本号>随着provider的版本更新而变化。

如果你不知道Provider的名称,可以通过如下的代码获得当前所有注册的Provider的名称。

FdoPtr<FdoProviderRegistry> registry =

(FdoProviderRegistry *)FdoFeatureAccessManager::GetProviderRegistry();

FdoProviderCollection * providers = registry->GetProviders();

FdoStringP displayName;

FdoStringP internalName;

FdoPtr<FdoProvider> provider;

int count = providers->GetCount();

for(int i = 0; i < count; i++) {

provider = providers->GetItem(i);

internalName = provider->GetName();

displayName = provider->GetDisplayName();

......

}

1.1.3.2  一步连接和两步连接

在所有连接参数已知的情况下,只需一步就可完成建立FDO Provider连接。如果某些参数值只有在创建连接之后才可能获得,这时就需要使用两步连接。

1) 一步连接

用户设置了所需的连接参数,然后调用连接对象的Open()方法,如果返回的状态是FdoConnectionState_Open,一步连接就完成了。

2) 两步连接

用户设置了所需的连接参数,然后调用连接对象的Open()方法,如果返回的状态是FdoConnectionState_Pending,则连接尚未完成。首次调用Open()只是为了得到第二次调用Open()所需的参数,在得到所需的连接参数后,第二次调用Open()方法返回的状态应该就是FdoConnectionState_Open了。

例如创建对MySQLArcSDE Provider的连接时,既可以通过一步也可以通过两步完成。在第一步时,Data Store参数不是必需的,如果用户可以不指定该参数,在第一步连接完成后可以执行列举Data Store的命令得到数据源Data Store的列表,从而让用户为第二步的参数做出选择,此时连接需两步完成;如果用户在第一步指定了正确的Data Store参数值,那么可以一步完成创建连接。

1.1.3.3  创建连接示例

假设用户已经安装了MySQL,并且在安装时设置了系统管理员帐号名为“root”,密码为“test”,以下是创建MySQL Provider连接的基本步骤。

// 得到连接管理器实例

FdoPtr<FdoConnectionManager> connectMgr =

(FdoConnectionManager *)FdoFeatureAccessManager::GetConnectionManager();

// 调用连接管理器CreateConnection()方法,把Provider名字作为该方法的参数

FdoPtr<FdoIConnection> fdoConnection =

connectMgr->CreateConnection(L”OSGeo.MySQL.3.4”);

//调用连接对象的GetConnectionInfo()方法来得到连接信息对象

FdoPtr<FdoIConnectionInfo> info = fdoConnection->GetConnection Info();

// 得到连接参数字典对象

FdoPtr<FdoIConnectionPropertyDictionary> ConnDict = info->GetConnectionProperties();

// 设置连接参数

ConnDict->SetProperty(L”Username”, L”root”);

ConnDict->SetProperty(L”Password”, L”test”);

ConnDict->SetProperty(L”Service”, L”localhost”);

ConnDict->SetProperty(L”Datastore”, L”fdo_user”);

// 打开连接

FdoConnectionState state = fdoConnection->Open();

以上四SetProperty()方法等价于SetConnectionString(…),所以上面的代码等价于如下的代码

FdoPtr<FdoConnectionManager> connectMgr =

(FdoConnectionManager *)FdoFeatureAccessManager::GetConnectionManager();

FdoPtr<FdoIConnection> fdoConnection =

connectMgr->CreateConnection(L”OSGeo.MySQL.3.4”);

// 设置连接字符串

fdoconnection->SetConnectionString(

L”Username=root;Password=test;Service=localhost;Datastore=fdo_user”);

// 打开连接

FdoConnectionState state = fdoConnection->Open();

每种不同类型的Provider使用了不同的连接参数,例如创建一个MySQL Provider的连接需要参数UsernamePasswordServiceDatastore,而创建一个SDF Provider的连接需要参数FileReadonly。如果想知道创建一个Provider的连接需要哪些参数,以及这些参数的名称、默认值、是否可选等信息,可以通过连接参数字典类FdoIConnectionPropertyDictionary获得这些信息。假设ConnDictFdoIConnectionPropertyDictionary的一个实例,使用如下的代码可以枚举Provider的所有连接参数,以及这些参数的属性。

FdoInt32 count = 0;

FdoString ** names = NULL;

FdoStringP name;

FdoStringP localname;

FdoStringP val;

FdoStringP defaultVal;

bool isRequired = false;

bool isProtected = false;

bool isFilename = false;

bool isFilepath = false;

bool isDatastorename = false;

bool isEnumerable = false;

FdoInt32 enumCount = 0;

FdoString ** enumNames = NULL;

FdoStringP enumName;

names = ConnDict->GetPropertyNames(count);

for(int i = 0; i < count; i++) {

name = names[i];

val = dict->GetProperty(name);

defaultVal = dict->GetPropertyDefault(name);

localname = dict->GetLocalizedName(name);

isRequired = dict->IsPropertyRequired(name);

isProtected = dict->IsPropertyProtected(name);

isFilename = dict->IsPropertyFileName(name);

isFilepath = dict->IsPropertyFilePath(name);

isDatastorename = dict->IsPropertyDatastoreName(name);

isEnumerable = dict->IsPropertyEnumerable(name);

if (isEnumerable) {

if (isRequired) {

enumNames = dict->EnumeratePropertyValues(name, enumCount);

for(int j = 0; j < enumCount; j++) {

enumName = enumNames[j];

}

}

}

}

调用连接参数字典的GetLocalizedName()方法得到要显示给用户的本地化属性名,此时需要GetPropertyNames()函数返回的连接参数名称作为参数。调用IsPropertyRequired()方法可以得知某连接参数是可选还是必选。调用IsPropertyProtected()方法来决定某连接参数是不是受保护的,例如密码,此时的密码输入文本框不应显示明码。

调用IsPropertyEnumerable()IsRequired()方法来决定是否需要调用EnumeratePropertyValues()方法以得到合法值列表。只有这两个方法同时返回TRUE才能调用EnumeratePropertyValues()方法,否则如果此时没有挂起的连接,该方法会抛出异常。

从上面的示例代码可以看出,EnumeratePropertyValues()方法有两个参数,属性名和一个整数引用,返回字符串数组。整数引用的值说明了返回的数组包含字符串的数量。如果属性是可枚举的,就把返回的选项列表显示给用户;如果属性不是可枚举的,可以把GetProperty()GetPropertyDefault()的返回值显示给用户。

下面我们再来看一个二次连接的例子,如下的代码首先创建了一个MySQL Provider连接,然后创建了一个新的Data Store,最后连接到这个Data Store

// 创建连接

FdoPtr<FdoConnectionManager> connectMgr =

(FdoConnectionManager *)FdoFeatureAccessManager::GetConnectionManager();

FdoPtr<FdoIConnection> fdoConnection =

connectMgr->CreateConnection(L”OSGeo.MySQL.3.4”);

 

// 第一次打开连接

fdoconnection->SetConnectionString(L”Username=root;Password=test;Service=localhost”);

FdoConnectionState state = fdoConnection->Open();

 

// 创建新的Data Store

FdoPtr<FdoICreateDataStore> createDataStoreCmd = dynamic_cast<FdoICreateDataStore *>

(fdoConnection->CreateCommand(FdoCommandType_CreateDataStore));

FdoPtr<FdoIDataStorePropertyDictionary> createDsDict =

createDataStoreCmd->GetDataStoreProperties();

createDsDict->SetProperty(LDataStore, Lfdo_user);

createDataStoreCmd->Execute();

 

// 第二次打开连接

state = fdoConnection->Open();

第一次调用连接对象的Open()方法,返回的状态是FdoConnectionState_Pending,这时可以用挂起的连接创建Data StoreData store创建之后,再次调用连接对象的Open()方法,返回的就应该是FdoConnectionState_Open了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值