我正在尝试使用Crystal Report打印候选人的信息。
candidate_id位于候选班级中,我想要的是在我的报告类中获取此ID以针对该candidate_id
打印CrystalReport。
以下是我的候选班级代码
public partial class Candidate : System.Web.UI.Page {
string candidate_id;
public String CandId {
get { return candidate_id; }
set {
//getting id stored in session and setting its value
candidate_id = Convert.ToString(Session["candidate_id_in_session"]);
}
}
这是我的报告类,我想要 candidate_id
public class Report {
public static DataSet LoadReport() {
string candidate_val;
Candidate can = new Candidate();
candidate_val = can.CandId;
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand command = new SqlCommand(
"SELECT * From personal_information " +
"WHERE candidateNo = @candidate_val", myConn
);
command.Parameters.AddWithValue("@candidate_val",candidate_val);
da.SelectCommand = command;
DataSet ds = new DataSet();
da.Fill(ds, "personal_information");
return ds;
}
}
我正在接受以下异常,这显然意味着我没有从另一个班级获得candidate_id
。
System.Data.SqlClient.SqlException: The parameterized query '(@ nvarchar(4000))SELECT * From personal_information WHERE c' expects the parameter '@candidate_val', which was not supplied.
请告诉我我在哪里做错了?
我已经检查了在setter中设置的值但是没有在getter中返回,而另一个有趣的事情是,如果我在getter中返回硬编码值,那么它将被传递给另一个类。
答案 0 :(得分:4)
您在此行中提供null
值:
command.Parameters.AddWithValue("@candidate_val",candidate_val);
因为你设置candidate_val
是这样的:
Candidate can = new Candidate();
candidate_val = can.CandId;
在新创建的Candidate
中,未设置CandId
,CandId
的值为null
。
同样,CandId
属性的实现有点奇怪。我会像这样实现它:
public String CandId {
get { return Convert.ToString(Session["candidate_id_in_session"]; }
set { Session["candidate_id_in_session"] = value; }
}
否则你必须调用CandId = <any value you want>
来将会话中的值传入CandId
属性 - 这有多合乎逻辑?
作为一名程序员,我希望该属性返回当前值,并在设置时更改当前值,这不是您的实现所做的。
因为评论中提到过:要明确地将参数设置为DBNull
,您需要这样的内容:
command.Parameters.AddWithValue("@candidate_val",candidate_val ?? DBNull.Value);
只是为了让它更清晰:我认为这是非常糟糕的风格实现这样的属性!如果我打电话
CandId = "Hello";
我希望该属性的值为“Hello”而不是其他内容,因为它就是你的情况!
从评论中我得到你甚至不想设置属性。然后你应该像这样修改它:
public String CandId {
get { return Convert.ToString(Session["candidate_id_in_session"]; }
}
最终修改
您正在实施的设计计划不周。类Report
实际上独立于任何与UI / web /交互相关的东西,而是纯粹的业务逻辑类。事实上,无论您是在ASP.NET,WinForms,WPF还是Windows Service项目中使用此类,它都无关紧要。为什么要通过使其访问ASP.NET会话来引入依赖项?这没有理由,也不应该这样做(就像业务逻辑不应该显示错误消息一样)。
您应该更改方法,以便他们将所需的值作为参数(当您使用它们时,正确地释放资源):
public class Report {
public static DataSet LoadReport(string candidate_val) {
using (SqlCommand command = new SqlCommand("SELECT * From personal_information WHERE candidateNo = @candidate_val", myConn))
using (SqlDataAdapter da = new SqlDataAdapter(command))
{
command.Parameters.AddWithValue("@candidate_val",candidate_val);
DataSet ds = new DataSet();
da.Fill(ds, "personal_information");
return ds;
}
}
}
如果这样做,只需调用LoadReport
函数就可以解决问题:
DataSet ds = Report.LoadReport(Convert.ToString(Session["candidate_id_in_session"]));
答案 1 :(得分:0)
要解决的一个重要说明:
您无法在Setter
:
candidate_id = Convert.ToString(Session["candidate_id_in_session"]);
而是将其写为:
public partial class Candidate : System.Web.UI.Page
{
string candidate_val;
public String CandId {
get { return candidate_id; }
set { candidate_id = value; }
}
}
现在,您正在尝试将id存储在会话中。然后您可以直接将会话变量用作:
public partial class Candidate : System.Web.UI.Page
{
public String CandId {
get { return Convert.ToString(Session["candidate_id_in_session"]); }
set { Session["candidate_id_in_session"] = value; }
}
}