水晶报表开发部署常见棘手问题

 

  1. 报Log4net错误

    如图所示

    水晶报表开发部署常见棘手问题

    出现这样的错误,请查看C:\Windows\assembly目录下的log4net处理器体系结构

    水晶报表开发部署常见棘手问题

    当然不止x86结构了,可能会有amd64之类,在x86结构下,我们只需要设置IIS应用程序池x86处理,如图所示,只需启用32位应用程序。

    水晶报表开发部署常见棘手问题

    那么问题来了,如果log4net是基于amd64处理器体系结构,那怎么办?

  2. 已达到系统管理员配置的最大报表处理作业数限制

    出现这样的问题,有两种办法解决

      1. 办法一(修改注册表)

        出现这个问题,通常是水晶报表设置了打印次数限制,初始设置是75,那么出现打印次数这样的错误,我们需要设置注册表

        [HKEY_LOCAL_MACHINE\SOFTWARE\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0\Report Application Server\InprocServer]
         修改PrintJobLimit为最大数,或者设置为-1

         

        [HKEY_LOCAL_MACHINE\SOFTWARE\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0\Report Application Server\Server]
         修改PrintJobLimit为最大数,或者设置为-1

        注意:不同版本的水晶报表,对应的注册表结构不同,需要自己查找注册表的对应位置。

        如下图,水晶报表对应的位置

        水晶报表开发部署常见棘手问题

        水晶报表开发部署常见棘手问题

        水晶报表开发部署常见棘手问题

         

         

         

         

      2. 办法二(程序中设置创建ReportDocument对象队列)

        原理:当报表当前使用次数达到最大值的时候,我们将报表ReportDocument资源全部释放掉,重新创建ReportDocument对象。

    public class ReportFactory
    
    {
    
    	protected static Queue reportQueue = new Queue();
    
    	protected static int iMaxCount = 75;
    
    	protected static ReportDocument CreateReport(Type reportClass)
    
    	{
    
    		object report = Activator.CreateInstance(reportClass);
    
    		reportQueue.Enqueue(report);
    
    		return (ReportDocument)report;
    
    	
    
    	}
    
    	public static ReportDocument GetReport(Type reportClass)
    
    	{
    
    		if (reportQueue.Count > iMaxCount)
    
    		{
    
    			((ReportDocument)reportQueue.Dequeue()).Close();
    
    			((ReportDocument)reportQueue.Dequeue()).Dispose();
    
    			GC.Collect();
    
    		}
    
    		return CreateReport(reportClass);
    
    	}
    
    }
    
    
    
    调用方法
    
    
    
    CrystalDecisions.CrystalReports.Engine.ReportDocument crReportDocument = new ReportDocument();
    
    
    
    crReportDocument = ReportFactory.GetReport(crReportDocument.GetType());
    
    

      

  3. 多行文本对齐

    对于这样的问题,我尝试修改水晶报表内部javascript文件,或者使用代码调整,又或者调整内部脚本,没有一次能成功,尽管显示的时候,像word一样的效果,但是打印出来的结果,还是不会变。最后在google搜索下,这样的问题无法解决,最后对这个产品彻底失望。很奇怪的是,像这样的大型的水晶报表公司,连这个问题都无法解决,真是奇葩了。

  4. 出现通信错误。将停止打印

    这类问题很简单

    主要是两个问题引起的

    1. 报表数据绑定和报表属性配置的问题
      1. 如果是报表数据绑定

        如果不是报表配置的问题,请把相关的数据放入Page_Load(object sender, EventArgs e)

      2. 如果是报表属性配置,请把配置信息放入

        Page_Init(object sender, EventArgs e)

    2. 数据绑定问题

      出现这个问题,请把数据存储到session(适用不限于一个页面也可以在整个应用程序中使用)或者ViewState(适用单页面)中,比如这样

       

      If(Session["Report"]==null)
      
      {
      
      	boReportDocument = new ReportDocument();
      
      	boReportDocument.Load("reportname.rpt");
      
      	Session.Add("Report", boReportDocument);
      
      }
      
      CrystalReportViewer.ReportSource = Session["Report"];
      
      

        

      至于为什么为什么要在HttpSession存储ReportDocument对象,经过我的观察,当页面不断的回发加载报表的时候,同时也不断的在C盘window目录下temp创建临时ReportDocument文件,这样就不断的读写文件,那在高负载的这样的环境,是不是损失了很多性能?那为什么从磁盘加载报表在每次回发时可能是一个非常坏的主意?无疑有以下几个问题:

  • 高负载加载读取报表,所影响的性能?
  • 高负载数据库的重新查询,报表每一页的数据呈现所影响的性能?
  • 高负载增加应用服务器和数据库之间的网络流量,所影响的性能?
              3. 浏览器呈现报表问题

        呈现报表数据的时候,不要把报表页面嵌在iframe或者不同的http端口服务下下,尽管你的程序没有错误,但是弹出安装水晶报表activex控件的时候,这个时候页面会刷新,但刷新的不是当前呈现报表数据的窗口,而是iframe父窗口,这时可能activex控件安装可能就无法映射到当前呈现报表数据的窗口了,而是映射到了父窗口了,所以才会出现通信错误。同样不同http端口,也会出现这样的问题,据我的理解,应该是安装activex控件的时候,没有映射到具体的位置。以上是我对这个问题的理解,有错误,请指正。

  5.水晶报表刻度单位

    1. 水晶报表的最小度量单位其实是缇,1厘米=567缇,这个是他的精度。上移和下移手工拖动有时候动作会太大,可以这样做微调,点钟某个字段或对象,可以看到右边的属性框里有如下属性left,top,width等,可以输入这个值进行精确微调。其实就算换算微调,很难调准确,差距还是很大,必须用实际打印出来的报表,使用尺子去量。

  6.不支持的操作。无法在 C++ 堆栈中打开由 JRC 引擎处理的文档

 

  你得到这个错误的原因是文件名,路径无效或CR无法访问文件。如果路径和文件名都是正确无疑的,那么你要确保Network Service用户有读/写的Temp文件夹权限(一般C:\Windows\Temp)。如果还不能解决问题也许你的临时文件夹已满,CR没有清理垃圾。如果是这种情况,那么你需要适当的请求GC释放ReportDocument对象资源。

  有的时候,CR行为变幻莫测。当你使用ReportDocument对象调用Dispose()之后,随后GC.Collect可能仍然没有清理Temp文件夹。而且就算Temp文件夹中的.rpt文件没有任何限制,CR仍然也有可能停止执行ReportDocument释放资源请求。

  很奇怪,这些通常发生在内部函数或事件处理程序中的ReportDocument对象。但是,如果你声明一个全局的ReportDocument对象,并且调用Dispose方法,这时垃圾很快清理掉了。

释放资源代码样例 

        public override void Dispose()

        {

            try

            {



                if (this.CrystalReportViewer1 != null)

                {

                    this.CrystalReportViewer1.Dispose();

                    this.CrystalReportViewer1 = null;



                }

                if (reportdocument != null)

                {

                    reportdocument.Close();

                    reportdocument.Dispose();

                    GC.ReRegisterForFinalize(reportdocument);

                }

            }

            catch (Exception ex)

            {



            }

        }

        protected void Page_UnLoad(object sender, EventArgs e)

        {

            //建立完页面时,释放报表文档资源         

            try

            {



                if (this.CrystalReportViewer1 != null)

                {

                    this.CrystalReportViewer1.Dispose();

                   this.CrystalReportViewer1 = null;



                }

                if (reportdocument != null)

                {

                    reportdocument.Close();

                    reportdocument.Dispose();

                    GC.ReRegisterForFinalize(reportdocument);

                }

                this.Dispose();

                this.ClearChildState();

            }

            catch (Exception ex)

            {





            }

        }

  

 

你可能感兴趣的:(开发)