【问题标题】:Crystal Report: Missing Parameter ValuesCrystal Report:缺少参数值
【发布时间】:2011-02-12 17:51:43
【问题描述】:

我是 Crystal 报表的新手,应用程序位于 ASP.net 3.5 和 MySQL 5.1 中,将在从日期到至今的日期之间开发报表,报表的第一页显示良好,但是当我尝试在另一个页面上导航时我遇到了类似 Missing Parameter Values 的错误,我在打印和导出操作中遇到了同样的错误 提前致谢

公共部分类 BookingStatement:System.Web.UI.Page {

//DAL is my Data Access Layer Class

//Book 是 ReportClass

DAL obj = new DAL();
Book bkStmt = new Book();
protected void Page_Load(object sender, EventArgs e)
{

    if (!IsPostBack)
    {
       //crvBooking is Crystal Report Viewer
       //reportFill method is to fill Report 

        reportFill();
        crvBooking.EnableViewState = true;
        crvBooking.EnableParameterPrompt = false;
    }


   /* Also try reportFill() out side !IsPostBack but didn't work */


    //Check if the parmeters have been shown.
 /*   if ((ViewState["ParametersShown"] != null) && (ViewState["ParametersShown"].ToString() == "True"))
    {
        bkStmt.SetParameterValue(0, "20/04/2010");
        bkStmt.SetParameterValue(1, "20/04/2010");
    }*/

}


protected void crvBooking_navigate(object sender, CrystalDecisions.Web.NavigateEventArgs e)
{
   // reportFill();
}

protected void reportFill()
{

    //bkStmt.rpt is Report file
    //bookingstatment is View
    //bkStmt is ReportClass object of Book

    string rptPath = "bkStmt.rpt";

    string query = "select * from bookingstatment";


    crvBooking.RefreshReport();
    crvBooking.Height = 600;
    crvBooking.Width = 900;



    bkStmt.ResourceName = rptPath;


    String dtFrm = bkStmt.ParameterFields[0].CurrentValues.ToString();

    obj.SetCommandType(CommandType.Text);
    obj.CommText = query;
    DataTable dtst = obj.GetDataTable();

    crvBooking.ParameterFieldInfo.Clear();



    ParameterDiscreteValue discretevalue = new ParameterDiscreteValue();
    discretevalue.Value = "20/04/2010"; // Assign parameter
    ParameterValues values = new ParameterValues();
    values.Add(discretevalue);

    bkStmt.SetDataSource(dtst);

    ViewState["ParametersShown"] = "True";
    crvBooking.EnableViewState = true;

    bkStmt.DataDefinition.ParameterFields[0].ApplyCurrentValues(values);
    bkStmt.DataDefinition.ParameterFields[1].ApplyCurrentValues(values);


    crvBooking.ReportSource = bkStmt;
}

}

【问题讨论】:

    标签: c# asp.net mysql


    【解决方案1】:

    我在为水晶报表写SQL时,SQL中参数的代码是这样的:

    --Date Range
    (
    (table.datetime >= '{?Start Date}')
    and table.datetime < '{?End Date}')
    )
    
    --Location
    ('{?Facility}'= 'All' OR '{?Facility}' = table.location))
    

    当然,您始终可以选择将参数直接编程到 Crystal 中。这种方法效率不高,但有时更容易。

    【讨论】:

      【解决方案2】:

      出现此问题的原因似乎是 Crystal Reports 在发生回发时不会将其参数值保留在其 ViewState 中。因此,当CrystalReportViewer 尝试再次加载用作ReportSourceReportClass 时,参数值不再存在。

      我们成功使用的一个解决方案是在设置所有参数值后将ReportClass(即您的Crystal Report 对象)保存到Session,然后在每次回发时将其加载到CrystalReportViewer Page_Init 事件。一个例子:

      // instantiate the Crystal Report
      var report = new DeliveryLabelsSingle();
      
      // set the required parameters
      report.DataSourceConnections[0].SetConnection("DBServer", "DatabaseName", "DatabaseUser", "DatabasePassword");
      report.SetParameterValue("@Param1", "val1");
      report.SetParameterValue("@Param2", "val2");
      
      // set the data source of the viewer
      crvLabels.ReportSource = report;
      
      // save the report object in session for postback binding
      Session["rptDeliveryLabels"] = report;
      

      那么页面的 Page_Init 事件如下所示:

      protected void Page_Init(object sender, EventArgs e)
      {
          if (IsPostBack) {
              if (Session["rptDeliveryLabels"] != null) {
                  // cast the report from object to ReportClass so it can be set as the CrystalReportViewer ReportSource
                  // (All Crystal Reports inherit from ReportClass, so it serves as an acceptable data type through polymorphism)
                  crvLabels.ReportSource = (ReportClass)Session["rptDeliveryLabels"];
              }
          }
      }
      

      这样,我们将始终为查看器设置一个报表对象,该对象已经使用适当的值进行了初始化。

      使用这种方法要记住的一点是,您可能会很快填满服务器内存,尤其是在您有大量用户生成大量不同报告的情况下。所以一些家务是有序的。我们通过为所有包含报表的 ASP.NET 页面实现一个基类(以及因此报表加载代码)来实现这一点。在这个基类中,我们将报告中所有可能的Session 变量设置为空。像这样:

      // class definition for ASP.NET page containing CrystalReportViewer & associated report(s)
      public partial class DeliveryLabelPrint : BaseReport
      

      那么BaseReport的定义如下:

      public class BaseReport : System.Web.UI.Page
      {
          protected override void OnLoad(EventArgs e)
          {
              if (!IsPostBack) {
                  for (var i = 0; i < Session.Count; i++) {
                      var sv = Session[i];
                      // if this session variable contains a Crystal Report, destroy it
                      if (sv is ReportClass) {
                          sv = null;
                      }
                  }
      
                  base.OnLoad(e);
              }
          }
      }
      

      通过这种方式,您可以确保任何用户在任何给定时间仅在内存中拥有一份报告。

      如果内存是一个问题,即使使用这种方法,也可以将单个变量值存储在 Session & 然后在 Page_Init 中实例化一个新报告 & 在将其分配给之前用保存的值重新填充它CrystalReportViewer.ReportSource。但在我们的案例中,每天有 40 个用户提取 50 多个不同的报告,这种存储 ReportClass 对象的实现和伴随的内务管理,自 3 年前应用程序上线以来,我们没有遇到任何内存问题.我仍然建议在将此解决方案投入生产之前进行适当的负载测试和监控,因为结果可能会因具体实施而异。

      【讨论】:

        【解决方案3】:

        我不得不使用显式 ReportDocument 类型而不是 ReportClass,因为由于某种原因这会引发无效的强制转换,但除此之外,它的工作原理与宣传的 AFAICT 完全相同。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-02-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-06
          相关资源
          最近更新 更多