Reporting Services Extension:File Share Data Processing Extension全程指南

微软的Reporting Services逐渐被大众熟悉并接受。以前做过Reporting Services的项目,但是总结的不多。最近看到越多越多的报表项目是用Reporting Services来做,走出去看看才知道别人在做什么。

今天要涉及到的主题是Reporting Services Extension,报表扩展。其实我是要搭建一个报表设计,开发的工具箱。在以前的一篇文章中,提到过用Reporting Services+Remoting做的报表设计平台。Remoting客户端向服务器发送SQL语句,其实不是SQL语句,准确说是类似如下的语句:程序集;类;方法 把这个查询语句发送到Remoting服务器,服务器在GAC中去找对应的程序集和方法,反射调用之,返回数据集给报表设计器。这种结构的报表设计灵活性很强。特别是一些计算,字符串方面的处理,用SQL语句可能不方便,要写很多的T_SQL代码。但是如果用这种方法,充分发挥程序语言(C#)和数据库语言(T_SQL)的长处,把集合运算部分用T_SQL来处理,计算和字符文本的处理则留在C#代码中。

万丈高楼平地起,要做这样一个扩展,需要先熟悉Reporting Services提供了哪些可以扩展的方面。
如果您看过微软的例子,它提供了下面几个主要的例子(Extension Samples)
FormsAuthentication Sample 扩展报表服务器的验证方式
FsiDataExtension Sample  数据处理扩展
PolygonsCustomReportItem  自定义报表项
PrinterDelivery Sample  打印传送扩展

我主要关注的是FsiDataExtension ,它的位置在C:\Program Files\Microsoft SQL Server\90\Samples\Reporting Services\Extension Samples
代码结构如下图
image
这里面有几个主要的类:Connection,Command,DataParameter,DataReader,Transaction。
看到这几个类,您可能会心的一笑,这不就是ADO.NET的结构吗?
编译这个例子,生成程序集Microsoft.Samples.ReportingServices.FsiDataExtension.dll
部署这个例子
1)拷贝文件到报表服务器和设计器中,把Microsoft.Samples.ReportingServices.FsiDataExtension.dll拷贝到C:\Program Files\Microsoft SQL Server\MSSQL.3\Reporting Services\ReportServer\bin.
和C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies
2)修改配置文件RSReportServer.config and RSReportDesigner.config的Data元素
RSReportDesigner.config 文件的位置是 C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies。RSReportServer.config 位置在C:\Program Files\Microsoft SQL Server\MSSQL.3\Reporting Services\ReportServer
添加如下元素
<Extension Name="FSI" Type="Microsoft.Samples.ReportingServices.FsiDataExtension.FsiConnection,
Microsoft.Samples.ReportingServices.FsiDataExtension"/>
为了支持报表设计器,修改RSReportDesigner.config 的Designer元素,添加
<Extension Name="FSI" Type="Microsoft.ReportingServices.QueryDesigners.VDTQueryDesigner,
Microsoft.ReportingServices.QueryDesigners"/>
3)配置代码访问安全性
修改rssrvpolicy.config和rspreviewpolicy.config文件,它们的位置分别在在
C:\Program Files\Microsoft SQL Server\MSSQL.3\Reporting Services\ReportServer
和C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies
添加一个CodeGroup 元素,内容如下
<CodeGroup class="UnionCodeGroup"
   version="1"
   PermissionSetName="FullTrust"
   Name="FSICodeGroup"
   Description="Code group for my FSI data processing extension">
      <IMembershipCondition class="UrlMembershipCondition"
         version="1"
         Url="C:\Program Files\Microsoft SQL Server\MSSQL.3\Reporting Services\ReportServer\bin\Microsoft.Samples.ReportingServices.FsiDataExtension.dll"
       />
</CodeGroup>

不需要重启动电脑,打开Visual Studio 2005 BIDS,新建一个Reporting Services项目
 image
从图中看到,数据源中有File Share Information,选择它作为报表的数据源
新建数据集,输入查询字符串\\XX-PCName\\2010,XX-PCName是计算机的名字
image
这个扩展的目的是读取某台计算机的共享文件夹中的信息,作为数据集的内容。
执行这个数据集,得到的结果如下
image
设计报表,使用Table控件
image
预览报表,结果如预期所示
image 
虽然这个扩展没有多大的意义,但是它展示了如何去扩展Reporting Services的Data Process。

下面再来看看,FsiDataExtension项目的代码结构
image
再看看类图,大概了解有多少个类相互协作
image
再到代码里面看看,各自的关系
public sealed class FsiConnection : IDbConnectionExtension
public sealed class FsiCommand : IDbCommand
public sealed class FsiDataParameter : IDataParameter
public sealed class FsiDataParameterCollection : ArrayList, IDataParameterCollection
public sealed class FsiDataReader : IDataReader
public sealed class FsiTransaction : IDbTransaction
要正确编译这些类,需要引用Microsoft.ReportingServices.Interfaces.dll,实现它的接口
运用熟悉的ADO.NET的知识,打开IDbConnection接口
image 
IDbCommand的结构如下
image 
通过代码中的注释,一个查询语句传进来,它的流程应该是这样的
1)连接类型是FsiConnection,它是个空连接,不需要传入任何连接字符串。
因为权限的原因,设置当前连接主体WindowsIdentity
2)引擎根据查询代码和连接类型,调用如下构造方法
public FsiCommand(string cmdText, FsiConnection connection)  {
        m_cmdText = cmdText;       m_connection = connection;    
  }
最主要的还是IDbCommand.ExecuteReader(CommandBehavior behavior),它是执行查询命令的主要地方,它调用FsiDataReader,读取数据记录
reader = new FsiDataReader(m_cmdText);
reader.GetDirectory(m_cmdText);
进入数据读取类,它的读取代码如下
bool IDataReader.Read()
       {
           if (m_ie != null)
           {
               bool notEOF = m_ie.MoveNext();
               if (notEOF == true)
               {
                   m_currentRow++;
                   if (m_fsi[m_currentRow] is FileInfo)
                   {
                       FileInfo f = (FileInfo)m_fsi[m_currentRow];
                       m_cols[0] = f.Name;
                       m_cols[1] = f.Length.ToString(
                           System.Globalization.CultureInfo.InvariantCulture);
                       m_cols[2] = "File";
                       m_cols[3] = f.CreationTime.ToString();
                   }
                   else
                   {
                       DirectoryInfo d = (DirectoryInfo)m_fsi[m_currentRow];
                       m_cols[0] = d.Name;
                       m_cols[1] = "0";
                       m_cols[2] = "Directory";
                       m_cols[3] = d.CreationTime.ToString();
                   }
               }

               return notEOF;
           }

           return false;
       }
FsiDataReader定义了如下成员
internal String[] m_names = { "Name", "Size", "Type", "CreationDate" };
internal Type[] m_types = { typeof(String), typeof(long), typeof(String), typeof(DateTime) };
internal object[] m_cols = new object[4];
它有一个方法,根据传入的查询字符串,读取目录信息
internal void GetDirectory(string cmdText)
{
           ValidateCommandText(cmdText); 
           m_dir = new DirectoryInfo(cmdText);
           m_fsi = m_dir.GetFileSystemInfos(); 
           m_currentRow = -1;
           m_ie = m_fsi.GetEnumerator();
}
这样,借助于这些方法和接口,Fsi DataExtension Sample就可以部署到Reporting Services中,供报表设计和运行时使用。更多的细节请查看具体的代码。

我的主要目的是开头说到的,做开篇所说的那样的一个报表设计扩展。
如果有不熟悉的接口,请查阅MSDN。我根据自己的理解来论述,不恰当或错误之处欢迎批评指正。

posted @ 2010-03-29 14:50  信息化建设  阅读(2183)  评论(2编辑  收藏  举报