第五章--DMS对象介绍2


5.1、操作消息

5.1.1、消息概念介绍

在ProjectWiswe中允许用户向另一个用户发送消息或者收邮件,操作习惯就像在Windows上通过邮箱给他人发送邮件一样。ProjectWise中发送消息,是指给ProjectWise中的其他用户或者用户组发送文字消息,并且可以在发送消息时附加文件。

在学习ProjectWise如何发送消息之前,我们先介绍开发中会遇到的概念:消息列表对象、消息对象和消息。

消息列表对象:顾名思义,消息列表对象包含很有指定的消息,比如说,当前用户所有的发送消息,当前用户所有的未读消息,当前用户所有发送给指定用户的消息等。消息列表对象会根据不同的限定包含不同的消息对象。

消息对象:消息对象包含在消息列表中,可通过取消息列表中的某个指定下标元素获取到。消息对象是对消息内容的包装,不仅包含消息内容的信息,比如说,该消息的内容,该消息的附件等信息,还包括,消息创建后的记录信息,比如说,唯一的消息标识符、该消息的发送者,

消息:这个消息指的是消息的内容,是发送之前我们创建的消息,包含消息的标题、消息的内容和消息的附件等需要发送的内容。

消息列表对象、消息对象和消息这三个概念,在ProjectWise SDK中分别用HMSGLIST、HMSG和LPAAMSG表示。这三种类型或作为某个函数的参数或作为某个函数的返回值供我们在开发过程中使用。他们三者的关系如下图所示:

5.1.2、部分函数介绍

创建一个接受消息列表对象

                函数:HMSGLIST aaApi_MsgCreateReceivedList(ULONG ulStatus, ULONG ulSenderNo)

                介绍:这个函数创建一个包含被当前用户接收到处于指定状态消息的消息列表对象

                参数:[in]   ulStatus指定被包含消息所处的状态

                           [in] ulSenderNo 指定发送者的唯一用户标识符,如果这个参数是0,那么所有用户发送给当前用户的消息都将被包含进来。

                返回值:NULL 创建指定的消息列表失败。

                              Otherwise 返回消息列表对象的句柄

创建一个发送消息列表对象

                函数:HMSGLIST aaApi_MsgCreateSentList(ULONG ulReceiverNo)

                介绍:这个函数创建一个包含当前用户所发送的消息的消息对象列表。

                参数:[in] ulReceiverNo 指定一个唯一的接收者用户id。如果这个参数是0,那么被当前用户发给任意用户的消息都将包含在创建的消息列表对象中。

                返回值:NULL,创建消息列表失败

                              Otherwise,消息列表对象的句柄

获取消息列表对象中消息对象的个数

                函数:ULONG aaApi_MsgGetListCount(HMSGLIST hMsgList)

                介绍:这个函数获取指定消息列表对象中消息对象的个数

                参数:[in] hMsgList 指定消息列表对象的句柄

                返回值:0 获取消息列表中消息个数失败

                              Otherwise 消息列表中消息对象的个数

获取消息列表对象指定位置的消息对象

                函数:HMSG aaApi_MsgGetAt(HMSGLIST hMsgLIst, ULONG ulLoop)

                介绍:这个函数获取消息列表对象中指定位置的消息对象的句柄

                参数:[in] hMsgList 指定包含消息对象的消息列表对象的句柄

                           [in] ulLoop 指定要获取的消息对象在消息列表对象中的下标

                返回值:NULL 获取消息对象句柄失败

                              Otherwise 指定消息对象的句柄

获取指定消息对象的字符属性

                函数:LPCWSTR aaApi_MsgGetStringProperty(HMSG hMessage, ULONG ulPropld)

                介绍:这个函数获取指定消息对象的一个字符属性

                参数:[in] hMessage 要获取属性的消息对象的句柄

                           [in] ulPropld 指定要获取属性的标识符

                返回值:NULL 获取指定的字符属性失败

                              Otherwise 字符属性的值

获取指定消息对象的数值属性

                函数:LONG aaApi_MsgGetNumericProperty(HMSG hMessage, ULONG ulPropld)

                介绍:这个函数获取消息对象的数值属性

                参数:[in] hMessage 指定将获取数值属性的消息对象的句柄

                           [in] ulPropld 指定将获取的属性的标识符

                返回值:0 获取数值属性失败

                              Otherwise 数值属性的值

发送消息

                函数:BOOL aaApi_MsgSend(LPAAMSG lpAAMsg, HMSG *lphMsg)

                介绍:发送消息

                参数:[in, out] lpAAMsg 是一个包含将要发送消息的结构

                           [out] lphMsg 指向消息对象的句柄,如果这个参数是NULL,那么消息已发送出去这个对象就自动被销毁了,否则,这个参数将是创建的消息对象的句柄。

                返回值:FALSE 发送消息失败

                              TRUE发送消息成功

5.1.3、案例分析

5.1.3.1、如何发送消息

在这一部分,我们将给大家介绍如何发送消息。发送消息调用的函数是aaApi_MsgSend()。在这个函数中最重要的是第一个参数,所以在调用这个函数发送消息之前,我们首先需要准备一个LPAAMSG类型的变量,将我们要发送的消息内容放到这个变量内部,然后在调用函数发送出去。

LPAAMSG lpAAMsg =new AAMSG;
	lpAAMsg->ulMask =  AAMSG_SEND_ALL;
	lpAAMsg->lpctstrSubject = _MyTitle;//标题
	lpAAMsg->ulFlag = AAMSG_HIGH_IMPORTANCE;
	lpAAMsg->lpctstrMessage = _MyContent ;//通知内容
	lpAAMsg->ulAttachmentCount = 0;
	lpAAMsg->lpAttachments = 0;
	lpAAMsg->lpRecipients  = 0;
	lpAAMsg->ulRecipientCount=0;
	bool bRetVal = aaApi_MsgSend(lpAAMsg, NULL);
	long lErrorId=0; 
	if(bRetVal== true){
		AfxMessageBox(L"消息发送成功");
	}else{
		AfxMessageBox(L"消息发送失败");
		CString strError = aaApi_GetLastErrorMessage();
		lErrorId = aaApi_GetLastErrorId();
	}

5.1.3.2、如果获取消息

获取消息的过程相对比较复杂,首先第一步是先获取一个消息列表对象,消息列表对象中包含满足条件的所有消息对象;然后循环获取消息列表对象中指定下标中的消息对象;最后从获取到的消息对象中获取想要的消息内容。

HMSGLIST  hMsgList = aaApi_MsgCreateReceivedList(AAMSG_RECEIVED_UNREAD ,0); 
	//获取消息的数量
	long lCount = aaApi_MsgGetListCount(hMsgList);
	for(int i=0;i<lCount;i++){
		//获取下标为i中的消息对象
		HMSG hMsg = aaApi_MsgGetAt(hMsgList,i);
		//从消息对象中得到消息内容
		CString strContent = aaApi_MsgGetMessage(hMsg);
		//从消息对象中得到消息的标题
		CString strTitle = aaApi_MsgGetStringProperty(hMsg, AAMSG_PROP_SUBJECT);
		//从消息对象中得到该消息的唯一标识符
		LONG lMegId = aaApi_MsgGetNumericProperty(hMsg, AAMSG_PROP_ID);
	}

5.2、权限

5.2.1、权限介绍

ProjectWise中的权限控制是非常复杂的,在初始学习阶段,我们去繁从简,只学习简单的部分。所谓简单的部分就是只关心文件夹和文档方面的权限,其他方面的例如工作流和环境等的权限在这里将不再考虑。

首先看一下文件夹上面的权限。当我们给一个文件夹设置权限时,不仅可以设置它的Project/Folder Security部分还可以设置它的Document Security部分。Project/Folder Security部分的权限限定了当前用户操作该文件夹的能力,Document Security部分的权限限定了当前用户操作该文件夹下文档的能力。

接着我们看一下文档上面的权限。我们不仅可以在文件夹下设置权限,还可以单独针对该文件夹下的某个文档设置权限。此时该权限作用的对象只是该文档。

5.2.2、部分权限函数介绍

获取访问权限条目

                函数:LONG aaApi_SelectAccessControlItems2(ULONG ulFlags, LONG lObjectld1, LONG lObjectld2,LONG lWorkflowld, LONG lStateld, ULONG ulRequiredMask)

                介绍:这个函数根据指定的规则获取相应的访问权限。

                参数:[in] ulFlags 指定访问控制操作参数掩码,这个掩码指定了要获取的访问权限项的类型。

                           [in] lObjectType 指定了访问对象的类型。

                           [in] lObjectld1 指定了访问对象的首要id。如果访问对象是一个项目,那么这个参数是项目的id,如果访问对象是文档,那么这个参数是文档所属项目的id。如果访问对象是一个环境文档或者环境项目,那么这个参数是环境的id。

                           [in] lObjectld2 指定访问对象的次要参数,如果访问对象是一个文档,那么这个参数是文档的id,如果是其他对象,那么这个参数是0。

                           [in] lWorkflowld 指定工作流的id,如果这个参数是0,那么将获取直接访问对象上的基础权限控制条目,而不再关注工作流。

                           [in] lStateld 指定工作流的状态id,如果这个参数是0,那么将获取指定对象上面指定环境的所有状态的访问控制条目。

                           [in] ulRequiredMask 指定要获取的访问控制条目必须具有的访问权限掩码。

                返回值:0 获取访问控制条目属性失败,指定的访问控制不存在。

                              -1 获取访问控制条目属性失败,失败的错误码可以通过函数aaApi_GetLastErrorld()函数获取。

                               Otherwise 访问控制项的数目。

获取访问控制条目中的指定属性

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

                介绍:这个函数返回某个访问控制条目中指定的数值属性。

                参数:[in] lPropertyld, 指定要获取的访问控制条目中数值属性的id。

                           [in] lIndex 指定某个访问控制条目所处buffer的下标。

                返回值:0 获取属性失败

                              Otherwise 要获取的数值属性值。

5.2.3、案例分析

5.2.3.1、获取权限

获取权限我们需要用到两个函数,首先调用第一个函数aaApi_SelectAccessControlItems2()获取指定的访问控制项,然后调用第二个函数aaApi_GetAccessControlItemNumericProperty()获取访问控制项中的某些属性,其中包括权限拥有者的类型(用户、用户组、用户列表、ALL)、拥有者的id、权限作用对象的类型(文件、文件夹等)和实际权限值(创建、删除、可读、可写、可改…)等。

long numAccessRetVal = aaApi_SelectAccessControlItems2(AADMSFOAF_IGNORE_USERSETTINGS , AADMSAOTYPE_PROJECT , projectId , 0 , 0 , 0 , 0);
		if(numAccessRetVal<=0)
			return;
		for(int i = 0 ; i < numAccessRetVal ; i++)
		{
			long lObjtype = aaApi_GetAccessControlItemNumericProperty(ACCE_PROP_OBJTYPE, i); //对象类型: 2文件夹 4文件
			long lMemType = aaApi_GetAccessControlItemNumericProperty(ACCE_PROP_MEMTYPE, i); //用户类型: 1用户 2组 3userlist 4everyone 
			long lUserId = aaApi_GetAccessControlItemNumericProperty(ACCE_PROP_MEMID, i); //用户id
			long lAccess = aaApi_GetAccessControlItemNumericProperty(ACCE_PROP_ACCEMASK, i);//实际权限
			if(lMemType == AADMS_MGRTYPE_USER ){
				long numUserRetVal = aaApi_SelectUser(lUserId);
				if(numUserRetVal<=0)
					return;
				CString strUserName = aaApi_GetUserStringProperty(USER_PROP_NAME,0);
				if((lAccess&AADMS_ACCESS_CNTRL)!=0)
					AfxMessageBox(strUserName +L"-具有change权限!");
				else
					AfxMessageBox(strUserName +L"-不具有change权限!");
			}else if(lMemType == AADMS_MGRTYPE_GROUP ){
				long numGroupRetVal = aaApi_SelectGroup(lUserId);
				if(numGroupRetVal<=0)
					return;
				CString strGroupName = aaApi_GetGroupStringProperty(GROUP_PROP_NAME ,0);
				if((lAccess&AADMS_ACCESS_CREATE)!=0)
					AfxMessageBox(strGroupName +L"-具有create权限!");
				else
					AfxMessageBox(strGroupName +L"-不具有create权限!");
			}else if(lMemType == AADMS_MGRTYPE_USERLIST ){
				long numListRetVal = aaApi_SelectUserList(lUserId);
				if(numListRetVal<=0)
					return;
				CString strListName = aaApi_GetUserListStringProperty(USRLST_PROP_NAME  ,0);
				if((lAccess&AADMS_ACCESS_CREATE)!=0)
					AfxMessageBox(strListName +L"-具有create权限!");
				else
					AfxMessageBox(strListName +L"-不具有create权限!");

			}else {
				continue;
			}
		}

下面我们来分析一下这程序代码,首先调用函数aaApi_SelectAccessControlItems2(),该函数的第一个参数为AADMSFOAF_IGNORE_USERSETTINGS,表示忽略用户关于'use access control'的设置,第二个参数指定为AADMSAOTYPE_PROJECT,表示我们获取的访问对象类型是项目,那么此时这个函数的第三个参数就是项目的ID,第四个参数响应的就填0。第四个和第五个参数为0,表示我们不考虑作用在该项目上的工作流权限,只关心项目本身的权限,第六个参数为0表示获取的访问控制项没有必须拥有的权限掩码。这个函数调用结束后,将会把所有符合规则的访问控制项获取到指定的数据缓冲区中,并返回获取到的访问控制项的数目。

接下来,我们通过一个for循环,依次获取每一个访问控制项。在循环中,调用函数aaApi_GetAccessControlItemNumericProperty()获取指定访问控制项的属性信息,在代码中我们主要获取了四个属性,分别为ACCE_PROP_OBJTYPE表示该访问控制项做用的对象类型(返回值是2表示是一个文件夹,返回值是4表示是一个文档)、ACCE_PROP_MEMTYPE表示该访问控制项拥有者的类型(返回值是1表示时用户、返回值是2表示是组、返回值是3表示是用户列表、返回值是4表示是everyone)、ACCE_PROP_MEMID会根据ACCE_PROP_MEMTYPE值来决定它的id、ACCE_PROP_ACCEMASK表示该访问控制项所拥有的权限掩码,该值是一个数值,在获取实际权限值时我们需要与特定的权限掩码值进行位与操作(例如lAccess&AADMS_ACCESS_CREATE:判断是否有创建的权限)。

5.2..3.2、修改权限

我们在给项目后者文档设置权限时,主要用到的函数是aaApi_ApplyAccessControlList(),这个函数的参数比较复杂,顾我们没有在3.6.2章节进行介绍。在这一章我们将以实际使用情况给大家介绍该函数,另外关于更多的关于该函数的细节可参考SDK手册。

ObjectAccessEntry en[] = {{ 0, 0, AADMS_MGRTYPE_USER, lUserId, AADMS_ACCESS_FULL }};
			ObjectAccessSet set[] =
			{
				{AADMSAOTYPE_PROJECT, ARRAY_LENGTH (en), en}

			};
			if(aaApi_ApplyAccessControlList(ACL_CARRIER_FOLDER , lProjId , 0 , ARRAY_LENGTH (set) , set , SUBITEM_ACCESS_UNCHANGED))
			{
				AfxMessageBox(L"权限修改完成");
			}

这这部分代码中,我们主要介绍三个主要内容,首先是介绍上面的变量en,我们可以看到变量en是一个ObjectAccessEntry类型的数组,ObjectAccessEntry类型是一个访问控制项,它拥有五个成员,五个成员分别表示工作流id、状态id、用户类型、用户id和访问权限码。en数组是多个访问控制项的集合。

接着介绍的是变量set,这个变量是一个ObjectAccessSet类型的数组,ObjectAccessSet类型拥有三个成员,三个成员分别是访问控制项作用对象的类型(Project Or Document)、访问控制数组的长度和访问控制数组。

最后介绍的是函数aaApi_ApplyAccessControlList(),这个函数有五个参数,第一个参数很重要,它决定了set数组中能拥有什么类型的访问控制对象,例如,当是宏ACL_CARRIER_FOLDER时,set数组中的成员可以是访问控制项作用对象是Document的ObjectAccessSet变量、也可以是访问控制项作用对象是Folder的ObjectAccessSet变量。当第一个参数是宏ACL_CARRIER_DOCUMENT时,set数组中的成员只可以是访问控制项作用对象是Document的ObjectAccessSet变量。第二个参数和第三个参数会根据第一个参数的不同而具有不同的意义。第四个参数是set数组的长度。第五个参数是set数组。第六个参数是我们填入SUBITEM_ACCESS_UNCHANGED表示关于它子项的权限不变。

5.3、使用钩子

5.3.1、钩子概念介绍

钩子函数是这样的一种函数,在应用程序内部可以将它注册给指定动作来扩展或覆盖该动作的默认行为。这样在应用程序内部,该动作就会被监控起来,当该动作触发时,动作上注册的钩子函数就会适时响应。

何时响应,怎么响应会由钩子函数类型决定。钩子函数主要分为如下几种类型:

钩子函数可以添加到什么动作上?是由一个标识符来决定的,此标识是一个正数,可以由API定义的ID或是自定义ID。ProjectWise常用钩子ID,在ProjectWise SDK中Hook Identifiers章节中有详细说明。

所有基于ProjectWise API 的钩子函数必须以以下方式申明。

当为一个给定的ProjectWise 事件注册钩子函数时,开发者需要提供三部分相关信息。

下面我们以一张图展示钩子函数工作的的最简单模型。

在这个模型中,我们把某个PW动作分为三个时间段,一部分表示在默认动作触发前的时间段,第二部分表示在默认动作触发时的时间段,最后一部分表示在默认动作触发之后的时间段。在第一个和第三个时间段,默认情况下是不做任何处理的,只有在第二个时间段会存在一个默认的处理函数。当我们给这个动作添加钩子函数时,就可以在没有默认动作的第一和第二时间段添加动作,或者直接替换掉第二时间段中的默认动作。

当该PW动作被触发时,他是沿着先响应第一时间段中的钩子函数,在响应第二时间段中的钩子函数,如果这个时间段没有添加钩子函数就响应默认动作,最后响应第三时间段中的钩子函数。

5.3.2、部分函数介绍

为某事件添加钩子函数

                函数:BOOL aaApi_AddHook(LONG hHookld, LONG lHookType, AAPROC_OPERATION lpfnHook)

                介绍:这个函数添加一个钩子函数到指定动作的钩子链上,这个动作由lHookld指定

                参数:[in] lHookld 指定可被勾取函数的钩子标识符

                           [in] lHookType 指定钩子函数的类型

                           [in] lpfnHook 指定钩子函数的地址,如果这个参数没有指定或者是一个无效的钩子函数指针,这个函数调用将失败。

                返回值:FALSE 添加钩子函数失败

                              TRUE钩子函数添加成功

为某事件移除钩子函数

                函数:BOOL aaApi_RemoveHook(LONG lHookld, LONG lHookType, AAPROC_OPERATION lpfnHook)

                介绍:这个函数移除通过aaApi_AddHook()添加到指定钩子链中的钩子函数

                参数:[in] lHookld指定勾取函数的钩子标识符

                           [in] lHookType 指定钩子函数的类型

                           [in] lpfnHook 指定钩子函数的地址

                返回值:FALSE 移除钩子函数失败

                              TRUE 成功移除钩子函数

5.3.3、案例分析

在这一部分,我们将以Pw自带Sample中的例子给大家介绍钩子函数的具体使用方式。首先打开samples.sln工程,找到里面的hookimpl项目,打开其中的hookimpl.cpp。

在这个简单的项目中,首先第一步做的是调用aaApi_AddHook()函数为某个动作注册钩子函数。在一个PW dll工程中,我们选择在工程的CustomInitialize()函数中注册钩子,如下面的代码:

extern "C" LONG AAAPI CustomInitialize
(
ULONG           ulMask,     // i Application Mask
LPVOID          lpReserved  // i Reserved (must be NULL)
)
    {
    static BOOL bCustInitCalled = FALSE;

    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    if (!bCustInitCalled)
        {
        aaApi_AddHook (AAHOOK_MODIFY_PROJECT, AAPOSTHOOK, Hook_PostModifyProject);
        aaApi_AddHook (AAHOOK_MODIFY_PROJECT, AAPREHOOK, Hook_PreModifyProject);
        aaApi_AddHook (AAHOOK_PROJECT_PROPERTY_DLG, AAACTIONHOOK, Hook_ModifyProjectDlg);

        bCustInitCalled = TRUE;
        }

    return IDOK;
}

在这部分代码中,利用函数aaApi_AddHook()为动作AAHOOK_MODIFY_PROJECT和动作AAHOOK_PROJECT_PROPERTY_DLG注册了是三个钩子函数。

关于动作AAHOOK_MODIFY_PROJECT的解释如下:

                /**

* \brief This hook is used by aaApi_ModifyProject() and aaApi_ModifyProject2() functions.

*

* \details The handler must be of the type ::AAPROC_OPERATION.

*

* For more information on hook functions see \ref pwDevGuide_Hooks.

*

* \param aParam1   Pointer to a ::AAPRO_PARAM structure specifying project properties to modify.

* \param aParam2 Specifies the operation. Currently the only valid value is #AAOPER_PRO_MODIFY.

*

*/

            关于动作AAHOOK_PROJECT_PROPERTY_DLG的解释如下:

                /**

* \brief This hook is used by functions aaApi_ProjectPropertyDlg() and aaApi_ProjectPropertyDlg2().

*

* \details The handler must be of the type ::AAPROC_OPERATION.

*

* For more information on hook functions see \ref pwDevGuide_Hooks.

*

* \param   aParam1

* A pointer to the ::AAPROJECTDLG_PARAM structure specifying the Project Properties dialog parameters.

*

* \param   aParam2

* Specifies the operation. At the moment it is always #AAOPER_DLG_PROJPROPERTY.

*

*/

 第二步是编写钩子函数,本项目中就是编写Hook_PreModifyProject()、Hook_PostModifyProject()和Hook_ModifyProjectDlg(),下面以编写函数Hook_PreModifyProject()为例子给大家介绍。

一般我们编写的钩子函数模型如下:

LONG AAAPIHOOK Hook_PreModifyProject

(

LONG            /*hookId*/,

LONG           /*hookType*/,

AAPARAM         aParam1,

AAPARAM         aParam2,

AARESULT*       pResult

)

   {

            //具体的内容在此编写

   return AAHOOK_SUCCESS;

   }

最后一步是在结束的时刻,为某个动作移除我们为它注册的钩子函数,在本项目中,我们在最后的退出函数ExitInstance中移除注册了的钩子函数。

            int CHookimplApp::ExitInstance

(

)

   {

   LPVOID lpFakeHookPtr = NULL;

 

   aaApi_RemoveHook (AAHOOK_MODIFY_PROJECT, AAPOSTHOOK, Hook_PostModifyProject);

   aaApi_RemoveHook (AAHOOK_MODIFY_PROJECT, AAPREHOOK, Hook_PreModifyProject);

   aaApi_RemoveHook (AAHOOK_PROJECT_PROPERTY_DLG, AAACTIONHOOK, Hook_ModifyProjectDlg);

 

   return CWinApp::ExitInstance();

   }

5.4、操作数据库

5.4.1、数据库概念介绍

ProjectWise软件中所有数据信息都保存在相对应的数据库中,在创建数据源之初,我们将一个数据库与之绑定,这个数据库就是用来存储该数据源所有的数据信息,包括Explorer端的目录结构、文档名字和与之相关的所有属性信息,Administrator端的用户、环境和工作流等信息。

在界面上得到的信息我们直接操作与之对应的数据库也是可以得到的,只不过有时候表现形式不同而已。某些情况,为了更灵活的处理存取数据,很有必要直接操作数据库。这一章节,就给大家介绍一下关于ProjectWise数据库的知识。

ProjectWise数据中有很多表,分别存储不同的数据,下面我们针对几个常用的表给大家详细介绍一下。

5.4.1.1、DMS_DOC表

该表主要用于存储ProjectWise中和文档有关的数据,下面挑选几个表中关键的信息给大家介绍。

列名

数据类型

描述

o_docguid

guid

Unique document GUID

o_projguid

guid

Document project GUID

o_projectno

integer

Document project id.

o_itemno

integer

Document id

o_filename

varchar(127)

Document filename (empty if fileless document)

o_itemname

varchar(127)

Document name

o_itemdesc

varchar(127)

Document description

o_version

varchar(10)

Document version string

o_creatorno

integer

Creator user id

o_credatetime

timestamp

Create time

o_mgrtype

integer

Manager type (AADMS_MGRTYPE_*):

1 – Manager is a single user. 2 – Manager is a user group. 3 – Manager is a user list.

o_managerno

integer

Manager id (user id from dms_user table, group id from dms_grp or user list id from dms_ulst)

o_updaterno

integer

Document updater user id.

o_updatetime

timestamp

Update time

o_workflowno

integer

Workflow ID if document is assigned to it

o_stateno

integer

State ID if document is assigned to some workflow

o_applno

integer

Application id assigned to document

o_departno

integer

Department id assigned to document

5.4.1.2、 DMS_PROJ表

该表主要用于存储ProjectWise中和项目有关的数据,下面挑选表中几个关键的信息给大家介绍。

列名

数据类型

描述

o_projguid

guid

Unique project GUID

o_pprjguid

guid

Parent project GUID

o_projectno

integer

Unique project id

o_envno

integer

Environment id (reference to dms_env table).

o_parentno

integer

Parent project id (0 for top level vaults)

o_projectname

varchar(63)

Vault name.

o_projectdesc

varchar(127)

Description of the project.

o_version

varchar(10)

Project version string (not used)

o_mgrtype

integer

Manager type (AADMS_MGRTYPE_*):

1 – Manager is a single user. 2 – Manager is a user group. 3 – Manager is a user list.

o_projectmgr

integer

Manager id (user id from dms_user table, group id from dms_grp or user list id from dms_ulst)

o_creatorno

integer

User id of creator.

o_credatetime

timestamp

Create time.

o_subprojects

varchar(1)

‘Y’ if project has subprojects, ‘N’ otherwise

o_updaterno

integer

User id of last updater

o_updatetime

timestamp

Update time.

o_workflowno

integer

Id of workflow in which project is. 0 if in no workflow.

o_stateno

integer

Id of state in which project is. 0 if in no state.

5.4.1.3、 DMS_USER 表

该表主要用于存储ProjectWise用户的信息,下面挑选表中几个关键的信息给大家介绍。

Column name

Data type

Description

o_userno

integer

Unique user id.

o_usertype

varchar(1)

User type:

AADMS_DMSUSER(‘D’) ProjectWise internal user

AADMS_NTUSER(‘W’) Windows NT user

o_username

varchar(63)

User name

o_userdesc

varchar(127)

User description

o_passwd

varchar(43)

User password (encrypted)

5.4.1.4、DMS_STOR表

该表主要用来存储ProjectWise中存储区的信息,下面挑选表中几个关键的信息给大家介绍。

Column name

Data type

Description

o_storno            

integer

Unique storage id.

o_storname

varchar(63)

Unique storage name.

o_stordesc

varchar(127)

Description.

5.4.2、部分函数介绍

执行SQL语句

                函数:BOOL aaApi_ExecuteSqlStatement(LPCWSTR lpctstrSql)

                介绍:这个函数执行传入的SQL语句

                参数:[in] lpctstrSql 指定将要执行的SQL语句

                返回值:FALSE 执行SQL语句失败

                              TRUE 执行SQL语句成功

执行SQL获取语句

                函数:LONG aaApi_SqlSelect(LPCWSTR sqlString, LPCAABINDREQ pColumnBind, LPLONG lplColCount)

                介绍:这个函数执行给定的SQL获取语句,存储结果到静态缓冲区中。

                参数:[in] sqlString 指向将要执行的SQL获取语句。

                           [in] pColumnBind 详见帮助文档,

                           [in] lplColCount 是一个指向LONG类型的指针,存储结果表中列的个数

                返回值:0 没有行匹配获取策略

                              -1 执行SQL获取语句失败

                              Otherwise 获取到的结果的行数

获取SQL结果中某行某列的数据

                函数:LPCWSTR aaApi_SqlSelectGetData(LONG lIdxRow, LONG lIdxColumn)

                介绍:这个函数从相应静态缓冲区中获取一个数据

                参数:[in] lIdxRow 获取数据的行下标

                           [in] lIdxColumn 获取数据的列下表

                返回值:NULL 获取指定的值失败

                              Otherwise 返回指向结果数据的字符指针

5.4.3、案例分析

在这一部分我们将给大家演示如何将数据库的dms_doc表中前100项数据获取展示出来。首先调用函数aaApi_SqlSelect(),让其执行标准的SQL语句,获取dms_doc表中前100项数据;然后调用aaApi_SqlSelectGetStringProperty()函数获取dms_doc表的所有列名称信息,最后调用aaApi_SqlSelectGetData()函数获取指定位置的数据。

LONG lColCount = 1;
	LONG lRowCount = aaApi_SqlSelect (L"SELECT TOP 100 * FROM [ProjectWise].[dbo].[dms_doc]", NULL, &lColCount);
	CRect rect;
	_MySelectDataList.GetClientRect(&rect);
	for(int i=0;i<lColCount;i++){
		CString strValue = aaApi_SqlSelectGetStringProperty(SQLSELECT_COLUMN_NAME ,i);
		_MySelectDataList.InsertColumn(0, strValue, LVCFMT_CENTER, rect.Width() /4, 0);                 
	}
	for(int i=0;i<lRowCount;i++){
		for(int j =0;j<lColCount;j++){
			CString strValue = aaApi_SqlSelectGetData(i,j);
			if(j==0){
				_MySelectDataList.InsertItem(i,strValue);
			}
			_MySelectDataList.SetItemText(i,j,strValue);
		}
	}