第三章--获取PW数据的方式


获取PW数据的方式

ProjectWise软件是采用C\S架构进行设计的,ProjectWise中所有的数据,包括项目文件夹的分级结构,文件夹下文档的实际存储地址,文件夹和文档的属性信息,用户的所有配置信息等都是存储在S端的数据库中。

 针对这一系列信息的获取,ProjectWise SDK 中提供了两种方式供开发者使用,静态获取和动态获取方式。不同的方式有不同的优缺点,开发者在使用过程中可根据实际情况使用。

使用静态获取方式获取数据共分为两步,第一步调用相应的静态获取函数,从数据库中获取一系列数据到相应的静态缓冲区中,第二步调用相应的静态取值函数,从相应静态缓冲区里的一系列数据中得到相应的值。使用动态获取方式获取数据共分为三步,第一步调用相应的动态获取函数,从数据库中获取一系列数据到临时创建的动态缓冲区中,第二步调用相应的动态取值函数,从指定的动态缓冲区里的一系列数据中得到相应的值,第三步在数据取值完毕后,调用专门的函数销毁动态缓冲区。

2.1、获取数据到静态缓冲区

采用静态存储区获取数据的方式是开发者最常用的方式,如我们前面已经介绍,这种获取数据的方式分为两步来操作。第一步调用静态获取函数,将一系列数据从数据库中读取到内存中一个已存在的静态缓冲区里面,该静态缓冲区针对不同的DMS对象而不同。第二步调用静态取值函数,在保存了一系列相关数据的静态缓冲区中取出自己所需要的数据,该操作可在保证静态缓冲区没有被覆盖的情况下多次进行,以达到取出不同数据的需求。

采用静态存储区获取数据的方式具有很明显的优点,那就是操作简单(取数据过程只有两步),效率高(不需要额外申请空间)和对象针对性强(从SDK中可以看到,关于某一个DMS对象,都有一系列静态获取该对象相关数据的函数)

 采用静态存储区获取数据的方式最大的缺点就是静态存储区中的数据容易被覆盖。比如采用该方式获取项目对象的属性,由于获取项目的属性信息后,会将这些信息都存储到一个ID为AADMSBUFFER_PROJECT的静态缓冲区中,多次操作或者调用不同种类的获取函数都将操作这一个缓冲区,下一次获取后会直接覆盖上一次获取的内容。这样的机制将容易导致多线程下获取错误数据和不支持递归调用的缺点。

2.1.1、静态获取数据函数特点

在ProjectWise的SDK中,开发者采用静态缓冲区获取数据需要调用哪类函数?我们从ProjectWise SDK各DMS对象的函数中可以明显的看出来。下面我们以Project对象为例给大家介绍。

首先我们打开ProjectWise SDK开发文档,找到Modules分类下的ProjectWise DMS API系列,再找到该系列下的Project Functions部分。这一部分是关于项目(文件夹)DMS对象的函数,在这里我们主要关心数据获取函数。

 静态获取函数具有这样的特点:函数名以aaApi_Select…开头(函数名中不存在DataBuffer,返回值不是HAADMSBUFER类型的句柄),关于函数的解释一般是“This function selects …… into the static ProjectWise project buffer (buffer id is AADMSBUFFER_XXXXXX).” 。这一类函数就是从数据库中将所需的一系列数据获取到静态缓冲区中。

静态取值函数具有这样的特点:函数名以aaApi_Get…开头,关于函数的解释一般是“This function retrieves …… in the static ProjectWise …… properties buffer (buffer id is AADMSBUFFER_XXXXXX).” 。这一类函数就是从相应的静态缓冲区中取出指定的属性值。

特别注意,从函数名特征来区分函数的作用只能作为一种参考,具体函数功能还需仔细查看相应函数的解释。

2.1.2、部分函数介绍

获取指定ID的项目属性信息

                函数:LONG aaApi_SelectProject(LONG lProjectId)

                介绍:这个函数获取指定的项目属性信息,保存到ProjectWise静态缓冲区中(缓冲区 id是AADMSBUFFER_PROJECT)。这个函数调用后,该静态缓冲区中以前保存的数据将丢失。

                参数: [in] lProjectId 指定将要获取数据的项目的唯一ID

                返回值:1 数据获取成功

                               0 数据获取失败,原因可能是项目id无效或者项目没有找到

                              -1 数据获取失败,引起失败的错误码可通过函数aaApi_GetLastErrorId()获取

                              

获取当前数据源下的所有项目属性信息

                函数:LONG aaApi_SelectAllProjects(VOID)

                介绍:这个函数获取当前数据源下所有的项目属性信息,保存到静态缓冲区中(缓冲区 id是AADMSBUFFER_PROJECT)。这个函数调用后,该静态缓冲区中以前保存的数据将丢失。

                返回值:0 获取数据失败,当前数据源下没有项目

                              -1 数据获取失败,引起失败的错误码可通过函数aaApi_GetLastErrorId()获取

                               Otherwise 保存到静态缓冲区中的项目个数

 

获取指定项目的子项目属性信息

                函数:LONG aaApi_SelectChildProjects(LONG lProjectId)

                介绍:这个函数获取指定项目的直接子项目属性信息,保存到ProjectWise静态缓冲区中(缓冲区 id是AADMSBUFFER_PROJECT)。这个函数调用后,该静态缓冲区中以前保存的数据将丢失。

                参数: [in] lProjectId 指定将要获取的子项目数据的项目的唯一ID

                返回值:0 获取数据失败,指定项目下没有子项目

                              -1 获取数据失败,引起失败的错误码可通过函数aaApi_GetLastErrorId()获取

                               Otherwise 保存到静态缓冲区中的子项目的个数

 

获取当前数据源顶层项目属性信息

                函数:LONG aaApi_SelectTopLevelProjects(VOID)

                介绍:这个函数获取当前数据源下的所有顶层项目的属性信息,保存到ProjectWise静态缓冲区中(缓冲区 id是AADMSBUFFER_PROJECT)。这个函数调用后,该静态缓冲区中以前保存的数据将丢失。

                返回值:0 获取数据失败,当前数据源下没有项目

                              -1 获取数据失败,引起失败的错误码可通过函数aaApi_GetLastErrorId()获取

                              Otherwise 保存到静态缓冲区中的项目个数

 

获取指定项目的父项目属性

                函数:LONG aaApi_SelectParentProject(LONG lProjectId)

                介绍:这个函数获取指定子项目的父项目的属性信息,保存到ProjectWise静态缓冲区中(缓冲区 id是AADMSBUFFER_PROJECT)。这个函数调用后,该静态缓冲区中以前保存的数据将丢失。

                参数: [in] lProjectId 将要获取的父项目属性的子项目的唯一ID

                返回值:1 获取数据成功

                               0 获取数据失败,无效的项目id或者指定的子项目是顶层项目

                              -1 获取数据失败,引起失败的错误码可通过函数aaApi_GetLastErrorId()获取

 

取出静态缓冲区中指定下标下的数值属性值

                函数:LONG aaApi_GetProjectNumericProperty(LONG lPropertyld, LONG lIndex)

                介绍:这个函数从静态缓冲区中的指定下标下,取出指定的数值属性数据值。(缓冲区ID是AADMSBUFFER_PROJECT)

                参数:[in] lPropertyId 指定要要获取的数值属性值的属性id。该值是一些宏定义,详细内容可查看SDK文档。

                           [in] lIndex 指定要取数据项在缓冲区中的下标位置

                返回值: 0 获取数据失败

                               Otherwise 取得的数值属性值

 

取出静态缓冲区中指定下标下的字符属性值

                函数:LPCWSTR aaApi_GetProjectStringProperty(LONG lPropertyId, LONG lIndex)

                介绍:这个函数从静态缓冲区中的指定下标下,取出指定的字符属性数据值。(缓冲区ID是AADMSBUFFER_PROJECT)

                参数:[in] lPropertyId 指定要要获取的字符属性值的属性id。该值是一些宏定义,详细内容可查看SDK文档。

                           [in] lIndex 指定要取数据项在缓冲区中的下标位置

                返回值: NULL 获取数据失败

                               Otherwise 返回值是指向包含所需项目属性值字符指针,这个指针是一个临时变量,不能保存下来用于后面使用。

2.1.3、静态获取项目对象属性信息

在这一部分我们将以静态获取项目属性信息为例子给大家详细介绍相关SDK函数的使用。

 首先我们通过VS新建一个基于对话框的PW MFC 应用程序,具体实现步骤可参考1.2.1章节。在该应用程序中我们主要实现两个功能,一个功能用于登录PW数据源,另一个功能用于输出当前数据源下的顶层目录信息。具体程序界面如下:

在“登录”按钮的响应函数中,我们写下如下的代码用于登录指定的数据源。

BOOL bLogInRetVal = aaApi_Login(AAAPIDB_ODBC,L"ProjectWise",L"projectwise",L"projectwise",NULL);
if(bLogInRetVal == TRUE){
	AfxMessageBox(_T("数据源登录成功!"));
}else{
	AfxMessageBox(_T("数据源登录失败!"));
}

关于登录函数aaApi_Login(……),第二个参数是要登录的数据源名称,第三个参数是要登录的用户的名称,第四个参数是要登录的用户的密码。其他参数的信息可查看SDK中的解释。

在“顶层目录”按钮的响应函数中,我们写下如下的代码用于输出当前数据源下顶层目录的基本信息(名称和ID)。

LONG lTopProjCount = aaApi_SelectTopLevelProjects();
for(int index =0;index<lTopProjCount;index++){
	CString strProjName = aaApi_GetProjectStringProperty(PROJ_PROP_NAME,index);
	LONG lPorjId = aaApi_GetProjectNumericProperty(PROJ_PROP_ID,index);
	CString strProjId(L"");
	strProjId.Format(L"%d",lPorjId);
	AfxMessageBox(L"项目名:" + strProjName +  L"\n项目ID:" + strProjId );
}

在这段代码中,首先调用静态获取函数aaApi_SelectTopLevelProjects(),该函数从数据库中将当前数据源中所有顶层项目信息全都获取出来,并存入一个ID为AADMSBUFFER_PROJECT的静态缓冲区中。当前数据源中有多少个顶层项目,该静态缓冲区中就会存储多少项顶层项目信息数据。上述代码,静态缓冲区中会存储lTopProjCount项顶层项目信息,下标分别为0- lTopProjCount-1。

接下来的代码是循环遍历AADMSBUFFER_PROJECT静态存储区,依次操作每一个顶层项目信息,这部分操作主要是调用静态取值函数aaApi_GetProjectStringProperty()取得项目的字符串属性PROJ_PROP_NAME和aaApi_GetProjectNumericProperty()取得项目的数值属性PROJ_PROP_ID。

2.2、获取数据到动态缓冲区

采用动态缓冲区获取数据的方式是开发者经常使用的另一种方式,如我们前面介绍的那样,使用这种方式获取数据主要分为三步。第一步调用动态获取函数,将一系列数据从数据库中读取到内存的动态缓冲区中,这个动态缓冲区是调用该函数的同时自动创建的。第二步利用第一步创建的动态缓冲区的句柄,使用动态取值函数,从动态缓冲区中取出相应的数据。第三步是在所有取值操作完毕后,利用空间释放函数,将创建的动态缓冲区释放掉,防止内存泄漏。

采用动态缓冲区获取数据的方式完美的解决了采用静态缓冲区获取数据方式的缺点,即它可以支持递归调用,不用担心原始内容被覆盖的问题。

当然该方式也有一些很明显的缺点,那就是需要开发者自己管理内存,很容易因为操作不当导致内存泄漏。

2.2.1、动态获取数据函数特点

在ProjectWise的SDK中,开发者想通过动态缓冲区获取数据时该调用哪些函数?我们从ProjectWise SDK各DMS对象的函数中可以明显的看出来。下面我们以Document对象为例给大家介绍。

首先我们打开ProjectWise SDK开发文档,找到Modules分类下的ProjectWise SDM API系列,再找到该系列下的Document Functions章节,在该章节下找到Document Select Functions部分。这一部分是关于文档DMS对象的处理函数。

从这一系列的DMS对象处理函数中我们可以发现一些具有这样特点的函数。函数名以aaApi_Select…DataBuffer…的结构出现,关于函数的解释一般是“This function selects …… into the dynamic data buffer.”。 这一类函数就是从数据库中获取指定的数据到自动创建的动态缓冲区中的函数。

特别注意,针对不同的DMS对象,静态获取函数都不相同,各DMS对象都有自己的动态获取函数。而动态取值函数和空间释放函数,各DMS对象都用的是一套。

2.2.2、部分函数介绍

获取指定文档的属性信息

                函数:HAADMSBUFFER aaApi_SelectDocumentDataBuffer(LONG lProjectld, LONG lDocumentld)

                介绍:这个函数获取指定文档的属性信息到动态缓冲区中(缓冲区id是AADMSBUFFER_DOCUMENT)

                参数:[in] lProjectld 指定唯一的项目id,这个参数必须大于0

                           [in] lDocumentld 指定唯一的文档id,这个参数必须大于等于0

                返回值:NULL 获取属性信息失败,可通过函数aaApi_GetLastErrorId()获取应该该错误的错误码

                              Otherwise 返回存储属性信息数据的动态缓冲区的句柄。

取得动态缓冲区内的数值属性值

                函数:LONG aaApi_DmsDataBufferGetNumericProperty(HAADMSBUFFER hDataBuffer, LONG lPropertyId, LONG lIdxRow)

                介绍:这个函数从指定下标的动态缓冲区空间中取得指定的数值属性值

                参数:[in] hDataBuffer 动态缓冲区的句柄

                           [in] lPropertyld 要获取的数值属性

                           [in] lIdxRow 动态缓冲区的下标

                返回值:0 获取数据失败

                              Otherwise 要获取的数值属性值

取得动态缓冲区内的字符串属性值

                函数:LONG aaApi_DmsDataBufferGetStringProperty(HAADMSBUFFER hDataBuffer, LONG lPropertyId, LONG lIdxRow)

                介绍:这个函数从指定下标的动态缓冲区空间中取得指定的字符串属性值

                参数:[in] hDataBuffer 动态缓冲区的句柄

                           [in] lPropertyld 要获取的字符串属性

                           [in] lIdxRow 动态缓冲区的下标

                返回值:NULL 获取字符串属性失败

                               Otherwise 返回指向所需字符串属性值的指针

 

释放动态缓冲区

                函数: VOID aaApi_DmsDataBufferFree(HAADMSBUFFER hDataBuffer)

                介绍:这个函数释放动态缓冲区的空间

                参数:[in] hDataBuffer 要释放的动态缓冲区的句柄

2.2.3 、动态获取文档对象属性信息

在这一部分我们将以动态获取某个文档属性信息为列子给大家详细介绍相关SDK函数的使用。

在这个实例中,为了主要展示动态获取数据的使用方法,因此规避开不必要的代码逻辑,使用函数aaApi_SelectDocumentDataBuffer()动态获取某个指定文档的属性信息时,为了简化代码,传参时直接传入该文档的文档id和其所处文件夹的项目id。接着调用aaApi_DmsDataBufferGetStringProperty()函数获取该文档的名称属性信息,通过对话框的方式输出出来,最后调用函数aaApi_DmsDataBufferFree()释放掉申请的动态内存空间。详细代码如下:

HAADMSBUFFER hBuffer = aaApi_SelectDocumentDataBuffer(94,2);
if(hBuffer!=NULL){
	CString strName = aaApi_DmsDataBufferGetStringProperty(hBuffer,DOC_PROP_NAME,0);
	AfxMessageBox(L"文件名:" + strName);
}
aaApi_DmsDataBufferFree(hBuffer);

上述代码中我们可以看到获取数据到动态缓冲区的三步操作,第一步调用动态获取函数,从数据库中将所需的数据获取到动态申请的内存缓冲区中,并返回指向该动态缓冲区的句柄,第二步调用动态取值函数,从第一步返回的句柄指向的动态缓冲区中取出数据,第三步,在操作完成后调用空间释放函数,将我们因调用动态获取函数而申请的内存空间释放掉。