无法从另一个类C#获取变量的值

时间:2014-02-25 08:20:30

标签: c# asp.net

我正在尝试使用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中返回硬编码值,那么它将被传递给另一个类。

2 个答案:

答案 0 :(得分:4)

您在此行中提供null值:

command.Parameters.AddWithValue("@candidate_val",candidate_val);

因为你设置candidate_val是这样的:

Candidate can = new Candidate();
candidate_val = can.CandId;

在新创建的Candidate中,未设置CandIdCandId的值为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; }
    }
}