水晶报表使用,解决相同数据库不同服务器使用同一个水晶报表模板问题?

      在使用asp.net时,做ERP系统时,水晶报表是经常被使用的,在asp.net 上有水晶报表的控件,那个网上有很多,这里就不多讲了,水晶报表有两种模式即push模式和pull模式,pull模式是:使用设计报表时的链接数据库驱动获取打印表格,这个不需要写sql语句,代码量非常少,push模式即自己构造需要sql语句,代码量大,扩展报表的功能。

       在一次项目中,我遇到需要使用水晶报表的api,这里水晶报表主要使用的api是:

    using CrystalDecisions.CrystalReports.Engine;
    using CrystalDecisions.ReportSource;
    using CrystalDecisions.Shared;

      有经验的知道打印报表需要使用Engine.ReportDocument.setdatabaseLogon(string,string,string,string);这只是其中的一个重载。这就是配置pull模式,设计连接的数据库。但是在下遇到了一个需求是:有个水晶报表模板,比如说是在A数据库上设计的,但是B服务器有一个和A服务器一样的数据库结构,为了以后维护客户资料方便,必须实现更改配置实现,水晶模板在两个A、B之间的切换,但是水晶报表模板不变。

     分析:这个需求显然是你不能使用sql语句进行push模式的操作。但是使用上面给出的api配置发现,直接报错:database log error;这个是我很是纠结,但是这个功能必须要实现,我也在网上找了很多资料,没有合理的解决。

     我的分析(不对的地方请指正),我想这个配置服务器的函数内部是怎么实现的呢,我在网上找了一个C# 反编译工具,进行查看,看看Sap公司在里面封装了何方神圣。我把图片贴出来方便大家理解:首先找到这个api函数,也就是CrystalDecisions.CrystalReports.Engine-》ReportDocument-》setdatabaseLogon。

         可以看到里面有个调用自身。继续往下面走,就发现:

      调用了一个表格登录,这是什么东西,莫着急,继续点击往下看。

   

到这里你应该明白了,原来这个登录数据库设置是在pull模式下,调用了默认的数据库服务器名和数据库,这也就明白了为什么在函数setdatabaselogon();上更改服务器名,虽然数据库一样,提示登录数据库失败的原因。

说了这么多,问题的根源终于找到了,但是怎么解决呢,这才是重点,从第三个图中可以看出它是 把信息应用到没哟个数据中,既然这样我们可以模仿他的方法进行重写自己的链接数据。

       

 1   #region 转换服务器连接
 2             ConnectionInfo connectinfo = new ConnectionInfo()
 3                {
 4                    ServerName = sqlhelper.CrystalStrServer,
 5                    DatabaseName = sqlhelper.CrystalDatabase,
 6                    UserID = sqlhelper.CrystalStrUser,
 7                    Password = sqlhelper.CrystalStrPwd
 8                };
 9             foreach (CrystalDecisions.CrystalReports.Engine.Table tb1 in rd.Database.Tables)
10             {
11                 tb1.LogOnInfo.ConnectionInfo = connectinfo;
12                 tb1.ApplyLogOnInfo(tb1.LogOnInfo);
13             }

这个代码使用可以解决你的问题,但是它会出现一点小BUG。什么bug呢,当你使用更改配置后假设使用A,使用默认水晶报表下载,下载的数据仍然是B的数据。怎么办呢,不要着急,在加一行代码就可以搞定了。

 CrystalDecisions.CrystalReports.Engine.ReportDocument rd = new ReportDocument();
            string rpt1 = Context.Server.MapPath("/CrystalReportsPath/" + StrGuid.Trim() + reportPath);
            rd.Load(rpt1);

            #region 转换服务器连接
            ConnectionInfo connectinfo = new ConnectionInfo()
               {
                   ServerName = sqlhelper.CrystalStrServer,
                   DatabaseName = sqlhelper.CrystalDatabase,
                   UserID = sqlhelper.CrystalStrUser,
                   Password = sqlhelper.CrystalStrPwd
               };
            foreach (CrystalDecisions.CrystalReports.Engine.Table tb1 in rd.Database.Tables)
            {
                tb1.LogOnInfo.ConnectionInfo = connectinfo;
                tb1.ApplyLogOnInfo(tb1.LogOnInfo);
            }
            //一定要刷新
            rd.Refresh();
            #endregion

  到这里问题就解决了。

posted @ 2015-11-03 17:52  Company  阅读(567)  评论(0编辑  收藏  举报