背景

最近项目上遇到一个需求,要后台通过定时任务把水晶报表生成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安装部署。

  • 这次奇迹出现了,顺利跑起来,生成了期待已久的报表文件!

总结

确认过眼神,要选对的人!~~~~~~~~

逻辑本身很简单,部署过程一波三折,运行时,版本匹配一定要牢记!

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

asp.net core使用水晶报表问题的更多相关文章

  1. Asp.Net中使用水晶报表

    Asp.Net中使用水晶报表(上) 在我们对VS.Net中的水晶报表(Crystal Reports)进行研究之前,我和我朋友对如何将这个复杂的东东加入我们的Web应用有着非常的好奇心.一周以后,在阅 ...

  2. Asp.Net中使用水晶报表(下)

    Asp.Net中使用水晶报表(下)   使用PUSH模式 我们采用下面的几步使用Push模式执行水晶报表: 1. 设计一个DataSet 2. 创建一个.rpt文件同时将其指定给上一步建立的DataS ...

  3. Asp.Net中使用水晶报表(中)

    Asp.Net中使用水晶报表(中) 使用Pull模式 我们将通过下面的这些步骤来通过Pull模式来执行水晶报表 1.首先创建rpt文件,并使用水晶报表设计接口设置一些必须的数据连接. 2.拖放一个 C ...

  4. Asp.Net 中使用 水晶报表(上)

    Asp.Net中使用水晶报表(上) 在我们对VS.Net中的水晶报表(Crystal Reports)进行研究之前,我和我朋友对如何将这个复杂的东东加入我们的Web应用有着非常的好奇心.一周以后,在阅 ...

  5. asp.net实现通用水晶报表

    此片博文是在你有一定水晶报表基础的前提下参阅的:如果对于水晶报表的基础知识比较薄弱建议先去了解下水晶报表: 因为项目需要,研究了下水晶报表.说实在,这个组件很强大,但是用起来也很麻烦.刚开始使用遇到了 ...

  6. ASP.NET Dev ASPxGridView控件使用 ASP.NET水晶报表打印

    1.ASPxGridView控件使用 2.ASP.NET水晶报表客户端打印 3.javascript打印 4.ASPxGridView根据Textbox查询 5. ASPxGridView 列宽 1. ...

  7. 水晶报表WEB方式下不打印的问题

    水晶报表版本是10.2.3600.0,是vs2005自带的.功能原来正常,服务器重做后不能打印,但是导出功能正常. 研究的大概情况: 1.水晶报表的web相关代码位于\aspnet_client\sy ...

  8. 2.ASP.NET MVC 中使用Crystal Report水晶报表

    上一篇,介绍了怎么导出Excel文件,这篇文章介绍在ASP.NET MVC中使用水晶报表. 项目源码下载:https://github.com/caofangsheng93/CrystalReport ...

  9. ASP.NET MVC 5使用CrystalReport(水晶报表)

    原文:ASP.NET MVC 5使用CrystalReport(水晶报表)   http://downloads.businessobjects.com/akdlm/cr4vs2010/CRforVS ...

随机推荐

  1. node 进程管理 child_process [spawn,exec] | 珠峰培训node正式课 网络爬虫

    run.js ; function set(){ i++ setTimeout(function(){ console.log(i) ){ set(); } },) }set(); child_pro ...

  2. self & _cmd

    https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles ...

  3. Codeforces 484 E. Sign on Fence

    [传送门] 题意就是给一排围栏,每个围栏都有一个高度,查询区间$\left[l, r\right]$之间长度为$w$的子区间的最小高度的最大值.首先,这个最大值肯定是这个区间里的围栏的某个高度,如果是 ...

  4. SPU、SKU、ARPU

    在涂涂商城开发之前,发现一篇关于电商中 SPU.SKU.ARPU 的介绍,转至博客,原文地址:http://www.ikent.me/blog/3017 什么是SPU.SKU.ARPU 首先,搞清楚商 ...

  5. Numpy | 09 高级索引

    NumPy 比一般的 Python 序列提供更多的索引方式.除了之前看到的用整数和切片的索引外,数组可以由整数数组索引.布尔索引及花式索引. 整数数组索引 实例1:获取数组中(0,0),(1,1)和( ...

  6. 如何查看WinDbg扩展有哪些命令

    如果您想查看任何windbg扩展所支持的命令,可以采用各种方法. 你可以用!<ext_name>.help命令查看该扩展支持的所有命令.用扩展模块名替换<ext_name>.( ...

  7. A1137 | 录数据查询模拟

    这应该是比较简单的一个模拟题,但是考试的时候花了较长的时间,并且最后一个case没过,丢了6分.这题的通过率不高,可见最后一个case还是有挑战性的. 考试的时候想的是在录数据的时候建立一个[ID]到 ...

  8. 数据库MySQL调优实战经验总结<转>

    数据库MySQL调优实战经验总结 MySQL 数据库的使用是非常的广泛,稳定性和安全性也非常好,经历了无数大小公司的验证.仅能够安装使用是远远不够的,MySQL 在使用中需要进行不断的调整参数或优化设 ...

  9. JS简单获取当前日期时间的方法(yyyy-MM-dd hh:mm:ss)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...

  10. 记一次phpmyadmin 4.8.1 远程文件包含漏洞(BUUCTF web)

    题目很简单,一个滑稽 打开源码,发现存在source.php文件 于是访问文件,发现出现一串php源码 提示存在hint.php,于是访问发现一句话 flag not here, and flag i ...