65.9K
CodeProject 正在变化。 阅读更多。
Home

以编程方式部署 Reporting Services 中的报表

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (10投票s)

2009 年 10 月 26 日

CPOL

3分钟阅读

viewsIcon

101410

downloadIcon

2682

如何在类似 BIDS 的方式中以编程方式部署您的报表

引言

或许是我的运气不好,或许是别的什么原因,我没有找到一个完整的帖子来说明如何在 Reporting Services 中以类似于 BIDS 的方式部署报表和数据源。

首先,我开发了一个工具来自动化 BI 解决方案的部署(创建数据仓库、安装 SSIS 包、创建作业、创建多维数据集和在 Reporting Services 服务器上安装报表)。

正文

在这里,我将重点介绍最后一项,即报表的部署。附注:这是我设计此类任务(在 Reporting Services 服务器上安装报表)的方式,它不是标准方式,也不是任何其他方式,只是“跟随你的心 :)”。让我们开始吧,我假设你、我或其他人都有这 3 个 XML 文件:一个用于文件夹,一个用于数据源,一个用于报表。

Folders XML File Scheme

Name:要在 Reporting Services 上创建的文件夹名称。
ParentFolder:'/' 表示位于顶部 == 没有父文件夹。

Data Sources' XML Scheme

名称
文件夹
描述
HideInListView
Enabled
ConnectionString
Extension
CredentialRetrieval
WindowsCredentials
ImpersonateUser
ImpersonateUserSpecified
Prompt
UserName
密码
EnabledSpecified
Name:要在 Reporting Services 上创建的数据源名称。
Folder:数据源应所在的文件夹,如果我们使用 '/' 表示位于顶部 == 没有父文件夹。
Description:数据源描述。
HideInListView:如果为 True,则在 Reporting Services 中隐藏它,否则为 False。
Enabled:如果为 True,则启用,否则不启用。
ConnectionString:数据源连接字符串。
Extension:根据提供程序配置,更多详情请参见下表...
提供商 Extension
Microsoft SQL Server SQL
OLE DB OLEDB
Microsoft SQL Server Analysis Services OLEDB-MD
Oracle ORACLE
ODBC ODBC
XML XML
SAP NetWeaver BI SAPBW
Hyperion Essbase ESSBASE
CredentialRetrieval:数据源如何检索凭据。
WindowsCredentials:如果为 True,则使用 Windows 凭据,否则将使用此 XML 中提供的凭据(用户名和密码)。
ImpersonateUser:指示报表服务器在数据处理扩展建立到数据源的已验证连接后,是否尝试模拟用户,使用存储的凭据。
ImpersonateUserSpecified:获取或设置一个值,指示是否指定了 ImpersonateUser 属性。
Prompt:获取或设置当报表服务器提示用户输入凭据时显示的提示。
UserName:获取或设置报表服务器用于连接到数据源的用户名。
Password:设置报表服务器用于连接到数据源的密码。只写。
EnabledSpecified:获取或设置一个值,指示是否指定了 Enabled 属性。
关于这些属性的更多详细信息 http://msdn.microsoft.com/en-us/library/reportservice2005.datasourcedefinition_properties.aspx

Reports' XML Scheme

Name:报表名称。
Path:.RDL 文件路径。
Folder:报表应所在的文件夹,如果我们使用 '/' 表示位于顶部 == 没有父文件夹。
DataSource:报表在 Reporting Services 中的数据源名称。以及这些配置键

Configuration keys

ReportsXMLFilePath:报表 XML 文件路径
DataSourcesXMLFilePath:数据源 XML 文件路径
FoldersXMLFilePath:文件夹 XML 文件路径
ReportingServerURL:Reporting Services 的 URL

打开 Visual Studio 并创建一个 C# 控制台应用程序(我们不需要与用户进行任何交互,所有配置都在应用程序配置文件中)。从项目主菜单中,选择“添加 Web 引用”或“添加服务引用”,然后选择“高级”,然后选择“添加 Web 引用...”

Add Web Reference

Add Reporting Services Reference

URL:http://{Server-Name}/reportserver/ReportService.asmx
Web reference name:给它一个有意义的名称...

我们所做的是添加了一个 Web 服务,通过它可以与 Reporting Services 通信,要求它执行某些操作(例如创建报表、创建数据源等)。让我们编写一些非常简单的 C# 代码。我们有一个名为 DeployReports 的方法,该方法按顺序调用 3 个其他方法:CreateFolders、CreateDataSources 和 CreateReports。

/// <summary>
/// Deploys Folders, DataSources, and Reports in Reporting Services by values configured in the application configuration file.
/// </summary>
private void DeployReports()
{
CreateFolders(
ConfigurationSettings.AppSettings["FoldersXMLFilePath"]);
CreateDataSources(
ConfigurationSettings.AppSettings["DataSourcesXMLFilePath"]);
CreateReports(Report.GetReports(
ConfigurationSettings.AppSettings["ReportsXMLFilePath"]));
}
/// <summary>
/// Creates Folder in Reporting Services.
/// </summary>
/// <param name="folderXMLFilePath"> XML file path holds folder information.</param>
private void CreateFolders(string folderXMLFilePath)
{
ReportingService reportingServicesClient =
new ReportingService(); 
reportingServicesClient.Credentials = System.Net.CredentialCache.DefaultCredentials; //default credential who runs the application
XDocument xmlDoc = XDocument.Load(folderXMLFilePath); //loads XML file to XDocument object
try
{
var result = from c in xmlDoc.Descendants(”Folder”) //gets Folder sections in the XMLDocument object (xmlDoc) 
select new //foreach <Folder> node get the value of <Name> node and <ParentFolder> node.
{
name = (string)c.Element(”Name”).Value,
parentFolder = (string)c.Element(”ParentFolder”).Value
};
foreach (var row in result)
{
reportingServicesClient.CreateFolder(row.name, row.parentFolder, null); //Creates new folder on the Reporting Service Server, it takes folder name and the parent folder name if parent folder name = '/' so there's no parent folder
Logging.Log(string.Format(”Folder {0} created successfully”, row.name)); //logs in case of success.  
}
}
catch (Exception er)
{
Logging.Log(er.Message);//logs in case of failure 
}
}
}
/// <summary>
/// Creates Data Sources in Reporting Services.
/// </summary>
/// <param name="datasourceXMLFilePath"> XML file path holds Data Sources information.</param>
private void CreateDataSources(string datasourceXMLFilePath)
{
ReportingService reportingServicesClient =
new ReportingService();
reportingServicesClient.Credentials = System.Net.CredentialCache.DefaultCredentials;//default credential who runs the application
DataSourceDefinition tempDataSource;  
XDocument xmlDoc = XDocument.Load(datasourceXMLFilePath);//loads XML file to XDocument object 
try
{
var result = from c in xmlDoc.Descendants(”DataSource”)//gets DataSource sections in the XMLDocument object (xmlDoc) 

select new //foreach <DataSource> node in the xmlDoc get name, folder, etc nodes
{
name = (string)c.Element(”Name”).Value,
folder = (string)c.Element(”Folder”).Value,
description = (string)c.Element(”Description”).Value,
hideInListView = (string)c.Element(”HideInListView”).Value,
enabled = (string)c.Element(”Enabled”).Value,
connectionString = (string)c.Element(”ConnectionString”).Value,
extension = (string)c.Element(”Extension”).Value,
credentialRetrieval = (string)c.Element(”CredentialRetrieval”).Value,
windowsCredentials = (string)c.Element(”WindowsCredentials”).Value,
impersonateUser = (string)c.Element(”ImpersonateUser”).Value,
impersonateUserSpecified = (string)c.Element(”ImpersonateUserSpecified”).Value,
prompt = (string)c.Element(”Prompt”).Value,
userName = (string)c.Element(”UserName”).Value,
password = (string)c.Element(”Password”).Value,
enabledSpecified = (string)c.Element(”EnabledSpecified”).Value
};
foreach (var row in result)
{
CredentialRetrievalEnum credentialRetrieval; //creates new instance from CredentialRetrievalEnum 
EnumConverter ec =
new EnumConverter(typeof(CredentialRetrievalEnum)); //creares new instance from EnumConverter to convert value string ((string)c.Element(”CredentialRetrieval”).Value) to CredentialRetrievalEnum 
credentialRetrieval = (CredentialRetrievalEnum)ec.ConvertFromString(row.credentialRetrieval); //here's how we converting
tempDataSource = new DataSourceDefinition(); //new DataSourceDefinition for each DataSource in xmlDoc
//here's setting some properties to tempDataSource from xmlDoc
tempDataSource.CredentialRetrieval = credentialRetrieval;
tempDataSource.ConnectString = row.connectionString;
tempDataSource.Enabled = bool.Parse(row.enabled);
tempDataSource.EnabledSpecified = bool.Parse(row.enabledSpecified);
tempDataSource.Extension = row.extension;
tempDataSource.ImpersonateUserSpecified = bool.Parse(row.impersonateUserSpecified);
tempDataSource.ImpersonateUser = bool.Parse(row.impersonateUser);
tempDataSource.Prompt = row.prompt;
tempDataSource.WindowsCredentials = bool.Parse(row.windowsCredentials);
if(!String.IsNullOrEmpty(row.userName))//if not null use username mentioned in the xml file
tempDataSource.UserName = row.userName;
if(!String.IsNullOrEmpty(row.password))//if not null use password mentioned in the xml file
tempDataSource.Password = row.password;
//user name and password should be used together....
try
{
reportingServicesClient.CreateDataSource(row.name, row.folder, true, tempDataSource,
null);//creates new datasource in the reporting service server
Logging.Log(string.Format(”Data Source {0} has created successfully”, row.name));//logs in case of success
}
catch (SoapException e)
{
Logging.Log(e.Detail.InnerXml.ToString());//logs soapException for more details on the exception occured
}
}
}
catch (Exception er)
{
Logging.Log(er.Message);//logs in case of failuar
}
}
/// <summary>
/// Creates Reports in Reporting Services.
/// </summary>
/// <param name="reports">Array from Report to be created on the Reporting Service Server.</param>
private void CreateReports(Report[] reports)
{
ReportingService rsc =
new ReportingService();
rsc.Credentials = System.Net.CredentialCache.DefaultCredentials;//use default credential 
foreach (Report aReport in reports)
{
Byte[] definition = null;//the defination of report
Warning[] warnings = null;//warning if there's warinign in report creation
try
{
FileStream stream = File.OpenRead(aReport.Path);
definition = new Byte[stream.Length];
stream.Read(definition, 0, (int)stream.Length);
stream.Close();
}
catch (IOException e)
{
Logging.Log(e.Message);//logs if there's an exception with the physical file
}
try
{
rsc.CreateReport(aReport.Name, aReport.Folder, true, definition, null);//creates new report on the Reporting Services Server
#region Setting Report Data Source
DataSourceReference reference = new DataSourceReference();//creates new instance from DataSourceReference 
reference.Reference = aReport.DataSource;//set the reference to the datasource name 
DataSource[] dataSources = new DataSource[1];//creates an array of 1 of DataSource
DataSource ds = new DataSource();//creates new instance of DataSource
ds.Item = (DataSourceDefinitionOrReference)reference;
ds.Name = aReport.DataSource.Split(’/').Last();//I just need the name not the full path so I split the full name of the datasource by '/' then get the last part like /1/2/3/4/5 I just need 5
dataSources[0] = ds;
rsc.SetReportDataSources(aReport.Folder + “/” + aReport.Name, dataSources);//sets report to datasource
#endregion
if (warnings != null)
{
foreach (Warning warning in warnings)
{
Logging.Log(string.Format(”Report: {0} has warnings”, warning.Message));//logs if there's any warning in the report creation
}
}
else
Logging.Log(string.Format(”Report: {0} created successfully with no warnings”, aReport.Name));//logs in case of success
}
catch (SoapException e)
{
Logging.Log(e.Detail.InnerXml.ToString());//logs more details on the error
}
}
}
Report\Logger 类将附加在源代码中...
我没有看到任何难以理解的代码来解释,任何熟悉 C# 的开发者都能很好地理解它,但如果你有任何问题,请随时问我。
© . All rights reserved.