asp.net core使用水晶報表問題


背景

最近項目上遇到一個需求,要后台通過定時任務把水晶報表生成pdf文件,然后郵件發送給相關人。

技術實現思路

選用ASP.NET Core框架(基於2.2版本),通過IHostedService接口結合Quartz實現定時任務。但由於當前水晶報表SDK只支持Framework框架,所以ASP.NET Core選擇基於.net framework 4.7。關於在ASP.NET Core下整合Quartz定時任務功能,在博客園里已經與很多的技術貼,不再贅述,特別要說明的一定,由於默認IIS托管,會導致應用程序池回收問題,會導致定時任務退出,所以如果IIS托管,需要設置應用程序池的啟動模式的值為AlwaysRunning閑置超時的值設置為0

下面言歸正傳,重點說下如何使用水晶報表。

  1. 下載Crystal Reports For VS的開發包,地址:https://www.crystalreports.com/crvs/confirm/

  2. 獲取rpt水晶報表模板文件

  3. 編碼實現導出功能

編碼

首先需要引用兩個程序集:CrystalDecisions.CrystalReports.Engine``CrystalDecisions.Shared

封裝的主要代碼邏輯

using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace CrontabService.Services.report

{
    public class CrystalReportGenerator
    {
        private ReportDocument _rd;
        private readonly ILogger<PurchaseNotifyMsgCreatorService> _logger;
        public CrystalReportGenerator(string templatePath, ConnectionInfo connectionInfo, ILogger<PurchaseNotifyMsgCreatorService> logger)
        {
            _logger = logger;
            TableLogOnInfo t = new TableLogOnInfo();
            t.ConnectionInfo = connectionInfo;
            _rd = new ReportDocument();
            _rd.Load(templatePath);
           foreach (Table table in _rd.Database.Tables)
           {
              table.ApplyLogOnInfo(t);
           }

                      
        }
        public string GenerateReport(Dictionary<string,object> paras,string reportFileName)
        {
            try
            {
                foreach (var kv in paras)
                {
                    _rd.SetParameterValue(kv.Key, kv.Value);
                }
                var reportPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"report\" + reportFileName);


                //導出為pdf格式
                _rd.ExportToDisk(ExportFormatType.PortableDocFormat, reportPath);
                return reportPath;
            }
            catch (Exception e)
            {
                _logger?.LogError(e, "GenerateReport error");


            }

        }
    }
}

其中ConnectionInfo類里面主要是數據庫的信息,這個里面需要把報表中應用到的表重新應用下數據庫連接信息,否則導出的時候,會提示數據庫連接失敗的錯誤

由於水晶報表有兩種獲取數據源的兩種方式:pushpull,push就是主動編碼設置數據源,調用方法SetDataSource既可以了,pull就是報表根據模板中維護的數據源信息,自己到數據庫中拉去信息。

因為我這個是后台任務去生成報表,所以就沒有 reportview的控件,這個里面我就遇到了問題了,我開始一直通過SetDataSource的方式去給數據源,結果一執行ExportToDisk方法就throw exception,提示數據庫連接失敗,后來網上找到解決方法,讓用pull方式,定義好數據庫連接,並把報表模板的參數值設置好,執行ExportToDisk就成功了,這個我猜測可能直接通過ReportDocument去導出時,默認還是用的pull方式,由於不熟悉水晶報表的使用,還忘大神指點!

遇到的坑

上面順利在開發環境測試成功,等發布后,部署到IIS后,出現一堆問題!

  • 出現無法加載log4net的異常錯誤,如下,一臉懵逼,怎么和log4net有關了,網上一頓研究,也有sap官方社區的回答,基本都是說編譯時的目標平台選擇有問題,應該選擇成X86,然后一頓狂試,無果,一直這個異常。
Could not load file or assembly ‘log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=692fbea5521e1304’ or one of its dependencies. The system cannot find the file specified
  • 實在沒轍,找了個32位的log4net放到目錄中,咦,換了個異常,提示沒有CrystalReports 的runtime,此時才意識到,開發環境,按照sdk時已經默認安裝運行時,生產環境沒有,還是到這個https://www.crystalreports.com/crvs/confirm/這個網站下載SAP Crystal Reports runtime engine for .NET framework,進行安裝

  • 信心滿滿的重啟,哎,奇跡還是沒有出現,又出現了新的異常,如下,空指針異常,my god,又是什么鬼,發現是執行_rd.ExportToDisk時異常,但_rd並不為null啊。

    System.NullReferenceException: 未將對象引用設置到對象的實例。
     在 CrystalDecisions.CrystalReports.Engine.FormatEngine.ExportToStream(ExportRequestContext reqContext)
     在 CrystalDecisions.CrystalReports.Engine.FormatEngine.Export(ExportRequestContext reqContext)
     在 CrystalDecisions.CrystalReports.Engine.ReportDocument.ExportToDisk(ExportFormatType formatType, String fileName)
    
  • 在一臉懵逼之際,自己神出鬼沒的取看了下運行時和sdk的版本

    SDK版本:CRforVS13SP25_0-10010309

    運行時版本:CR13SP26MSI64_0-10010309

下意識的看到一個是     SP25 ,一個是 SP26 ,難度是因為版本不一致導致的?

試試吧,到官網下載了新的SDK版本 CRforVS13SP26_0-10010309安裝部署。

  • 這次奇跡出現了,順利跑起來,生成了期待已久的報表文件!

總結

確認過眼神,要選對的人!~~~~~~~~

邏輯本身很簡單,部署過程一波三折,運行時,版本匹配一定要牢記!

最后,坑都是自己挖的,也是自己跳的,但自己再跳出來后,眼界可能有點不一樣了!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM