1. 问题分析
1.1 验证环境
Vistual Studio 2008
SQL Server2008
EPM2007(Project Server 2007)
1.2 问题场景
在某银行内部项目管理及数据仓库分析系统中,需要从EPM Project Server 2007服务中读取项目甘特图的计划数据,EPM2007通过基于Microsoft Office Sharepoint Server (MOSS)2007的Project Web Access(PWA)站点提供了较为完善的PSI Web Service接口,经过对PSI接口的分析,发现其数据的读取和写入,都主要以DataSet为基类的数据封装对象来完成,但如果单纯用C#读取PSI的项目数据再写入SQL Server数据库,需要较为大量的代码花在数据读取、关系映射和数据写入上边,代码量会比较大。最早也曾想到用SQL Server Integration Service(SSIS)控制流当中的执行Web Service任务来完成,但SSIS2008中提供的Web Service任务却还不能处理DataSet这样的复杂数据类型,只能处理String/DateTime之类的简单数据类型。由于以前有开发SQL Server Integration Service(SSIS)扩展开发控制流组件和数据流组件的经验,所以尝试用扩展开发SSIS数据源自定义组件的方式来调用PSI,读取EPM项目数据,成功获取了PSI中的Web Service 数据。
1.3 EPM PSI Web Service接口简介
Ø Project Server Interface (PSI)概述:
PSI是基于微软.NET Framework2.0 的一套Web Service编程接口,无论是Windows客户端的Project professional 或Web客户端的PWA 站点以及功能集成和二次开发都需要基于该编程接口。
Ø 使用PSI
要使用PSI针对Project Server 2007做二次开发需要理解PSI的架构,即PSI命名空间下的所有集合,如何创建并使用Web引用以及如何使用PSI方法的返回值类型:DataSet数据集。
1. 简介PSI Web服务
PSI为Project Server2007提供一整套托管代码应用程序接口,该接口作为一系列Web服务供Microsoft Windows和Web客户端以及Project Professional和PWA网站来访问。
例如,我们可以通过Web服务的关联文件Calendar.asmx来查看该Web服务提供的所有方法:
Project Server 2007拥有多层应用框架,对于应用层包括两层:Web服务层和业务逻辑层。而Web服务层包括了所有的PSI Web服务,他们用来调用位于业务逻辑层的业务对象。
EPM PSI接口多以DataSet对象为数据读取和写入的对象模型,如ProjectDataSet、CustomFieldDataSet、LookupTableDataSet等
2. PSI编程接口下的Web服务:
Web服务名称 | URL地址 | 服务简介 |
Admin | http:// youraddress/pwa/_vti_bin/psi/admin.asmx | PWA中的管理:设置财年、货币、报表时间段、内控日志、AD活动目录等 |
Archive | http:// youraddress/pwa/_vti_bin/psi/archive.asmx | 项目、安全类别、自定义域、资源、系统设置、视图等 |
Calendar | http:// youraddress/pwa/_vti_bin/psi/calendar.asmx | 管理企业日历:签入签出、建立删除更新日历个别项等等 |
CubeAdmin | http:// youraddress/pwa/_vti_bin/psi/cubeadmin.asmx | 管理OLAP Cube:取Analysis Server和数据状态、建立Cube、更改Cube定义等等 |
CustomField | http:// youraddress/pwa/_vti_bin/psi/customfield.asmx | 管理企业自定义域:签入签出、读取、建立、删除、更新等 |
LookupTable | http:// youraddress/pwa/_vti_bin/psi/lookuptable.asmx | 管理Lookup Table:多语言管理、代码掩码、签入签出、读取、建立、删除、更新 |
QueueSystem | http:// youraddress/pwa/_vti_bin/psi/queuesystem.asmx | 管理队列服务:取得队列中的任务数量、等待时间、任务状态等等 |
Resource | http:// youraddress/pwa/_vti_bin/psi/resource.asmx | 管理企业资源:签入签出、资源建立、更新、删除、查询等等 |
ResourcePlan | http:// youraddress/pwa/_vti_bin/psi/resourceplan.asmx | 管理资源计划:签入签出、建立、更新、删除等等 |
Security | http:// youraddress/pwa/_vti_bin/psi/security.asmx | 管理安全模板、安全类别、访问控制列表、全局权限、用户与组的权限等等 |
Statusing | http:// youraddress/pwa/_vti_bin/psi/statusing.asmx | 管理状态更新与分配:状态更新历史、用户审批历史、项目状态信息、工作分配状态信息等等 |
Timesheet | http:// youraddress/pwa/_vti_bin/psi/timesheet.asmx | 管理时间表:建立、删除、发布、更新、读取时间表 |
3. C#调用示例代码
用普通C#代码调用示例如下:
const string PROJECT_SERVER_URL = "http://epm2007:8888/PWA/";
const string PROJECT_SERVICE_PATH = "_vti_bin/psi/project.asmx";
ProjectSVC.Project projectSvc1 = new ProjectSVC.Project();//Web Service对象声明
projectSvc1.Url = PROJECT_SERVER_URL + PROJECT_SERVICE_PATH;
projectSvc1.Credentials = CredentialCache.DefaultCredentials;//需要客户机已保存有效的访问账号身份
ProjectSVC.ProjectDataSet pset=projectSvc1.ReadProjectList();//获取基于DataSet的项目列表
foreach (ProjectSVC.ProjectDataSet.ProjectRow projectRow in pset.Project)
{
Console.WriteLine(projectRow.PROJ_NAME + " (" + projectRow.PROJ_UID + ")");
}
1.4 SSIS扩展组件开发
SQL Server Integration Services 提供三种不同类型的数据流组件:源、转换和目标。源从数据存储区(如关系数据库中的表和视图、文件以及 Analysis Services 数据库)中提取数据。转换修改、汇总和清除数据。目标将数据加载到数据存储区,或创建内存中的数据集。
在我另一篇文章SQL Server Integration Service(SSIS)扩展开发自定义组件解决无效时间问题 http://blog.csdn.net/redbirdli/archive/2009/03/11/3980769.aspx 中,使用了自定义开数据转换组件的方式解决了无效日期数据的过滤问题(注:在SQL2008中已可通过数据类型DateTime2完美解决),这次经过分析,完全可以将 EPM PSI返回的数据对象封装成SSIS扩展开发的数据源组件
2. 实现步骤
2.1 组件实现
实现一个基于Microsoft.SqlServer.Dts.Pipeline.PipelineComponent
并在类前加上属性,如:
[DtsPipelineComponent(
DisplayName = "PSI LookupTable Source",
ComponentType = ComponentType.SourceAdapter,
IconResource = "Microsoft.Samples.SqlServer.Dts.AdoSource.ico"
)]
public class PSILookupTableSource : PipelineComponent
{………….
设置组件的成员、设计时、运行时相关代码,最为关键的是获取PSI DataSet的数据Schema,如:
private DataTable GetSchemaDataTable()
{
if (this.isConnected
&& this.httpClientConnection != null)
{
try
{
int psiTypeID = int.Parse(ComponentMetaData.CustomPropertyCollection["PSIObjectType"].Value.ToString());
return psiLib.GetLookupTableList().Tables[psiTypeID].CreateDataReader().GetSchemaTable();
}
catch
{
运行时数据获取:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "output"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
public override void PrimeOutput(int outputs, int[] outputIDs, PipelineBuffer[] buffers)
{
IDTSOutput100 output = ComponentMetaData.OutputCollection[0];
PipelineBuffer buffer = buffers[0];
try
{
int index = int.Parse(ComponentMetaData.CustomPropertyCollection["PSIObjectType"].Value.ToString());
FillData(buffer,psiLib.GetLookupTableList().Tables[index]);
// Notify the data flow that we are finished adding rows to the output.
}
2.2 组件安装
1.拷贝PSIDataSource.dll到
C:/Program Files/Microsoft SQL Server/100/DTS/PipelineComponents
注:文件夹位置可能会因SQL安装位置而不同(即使在X64环境下也为C:/Program Files (x86)/,因为SQL Server 的PipelineComponents此部分功能实际上还是32位实现);
2.打开Visual Studio 2008 命令提示工具,输入:
gacutil.exe /i "c:/Program Files/Microsoft Sql Server/100/DTS/PipelineComponents/PSIDataSource.dll"
3.打开SQL Server 2008 SSIS项目,选择并打开数据流任务
从左侧工具栏中“选择项”对话框中选取“SSIS数据流项”中的PSI LookupTable Source组件
2.3 组件使用
1.从数据源栏目中找到“PSI LookupTable Source”组件,并拖拽到数据流任务中
2. 使用方式与普通数据源组件差别不大,主要是配置一个HTTP数据连接,然后,组件通过Web Service调用,即可将PSI的DataSet通过封装,成为SSIS的数据输出了。
3. 同理,也可以设计PSI的数据目标组件,直接从SSIS输出DataSet到PSI,完成EPM项目数据的传送写入。
4. 另外,通过相同的思路,所有微软平台或非微软平台(如Java)提供的Web Service,只要可将Web 引用加入到项目时,封装成DataSet对象(这个封装过程可以在自定义数据源组件中new DataSet或DataTable填充数据来实现),就可以将其实现为图形化的SSIS数据流组件,加快开发的速度。
希望能对大家开发SSIS ETL提供连接异构系统的新思路。