C# 无法获取变量';来自另一个C类的s值#

C# 无法获取变量';来自另一个C类的s值#,c#,asp.net,C#,Asp.net,我正在尝试使用Crystal Report打印候选人的信息 候选id被放置在候选类中,我想要的是在我的报告类中获得该id,以便根据该候选id打印CrystalReport 下面是我的候选类代码 public partial class Candidate : System.Web.UI.Page { string candidate_id; public String CandId { get { return candidate_id; }

我正在尝试使用Crystal Report打印候选人的信息

候选id被放置在候选类中,我想要的是在我的报告类中获得该id,以便根据该
候选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"]); 
        }
    }
这是我的报告课,我想在这里获得候选人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;
    }
}
我得到了以下例外情况,这显然意味着我没有从另一个班级获得
候选人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中返回硬编码的值,那么它就会被传递给另一个类

在此行中提供一个
null
值:

command.Parameters.AddWithValue("@candidate_val",candidate_val);
因为您这样设置了
candidate\u val

Candidate can = new Candidate();
candidate_val = can.CandId;
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
    set { Session["candidate_id_in_session"] = value; }
}
command.Parameters.AddWithValue("@candidate_val",candidate_val ?? DBNull.Value);
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
}
而在新创建的
候选对象
中,未设置
CandId
CandId
的值为
null

另外,
CandId
属性的实现有些奇怪。我会这样实现它:

Candidate can = new Candidate();
candidate_val = can.CandId;
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
    set { Session["candidate_id_in_session"] = value; }
}
command.Parameters.AddWithValue("@candidate_val",candidate_val ?? DBNull.Value);
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
}
否则,您必须调用
CandId=
将会话中的值输入到
CandId
属性中-这有多符合逻辑

作为一名程序员,我希望属性返回当前值,并在设置时更改当前值,这不是您的实现所做的


因为注释中提到了它:要显式地将参数设置为
DBNull
,您需要如下所示:

Candidate can = new Candidate();
candidate_val = can.CandId;
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
    set { Session["candidate_id_in_session"] = value; }
}
command.Parameters.AddWithValue("@candidate_val",candidate_val ?? DBNull.Value);
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
}

更清楚地说:我认为这样实现属性是非常糟糕的风格!如果我打电话

CandId = "Hello";
我希望属性的值为“Hello”,而不是像您的情况那样的其他值


从我得到的评论来看,你甚至不想设置属性。然后您应该像这样修改它:

Candidate can = new Candidate();
candidate_val = can.CandId;
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
    set { Session["candidate_id_in_session"] = value; }
}
command.Parameters.AddWithValue("@candidate_val",candidate_val ?? DBNull.Value);
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
}

最终编辑

您正在实施的设计没有得到很好的规划。类
Report
实际上独立于任何与UI/web/interaction相关的东西,而是一个纯业务逻辑类。事实上,在ASP.NET、WinForms、WPF或Windows服务项目中使用此类都无关紧要。为什么要通过访问ASP.NET会话引入依赖项?没有理由这样做,也不应该这样做(就像业务逻辑不应该显示错误消息一样)

您应该更改这些方法,以便它们将所需的值作为参数(并且在使用时,适当地释放资源):

如果这样做了,只需调用
LoadReport
函数即可解决问题,如下所示:

DataSet ds = Report.LoadReport(Convert.ToString(Session["candidate_id_in_session"]));

在此行中提供一个
null
值:

command.Parameters.AddWithValue("@candidate_val",candidate_val);
因为您这样设置了
candidate\u val

Candidate can = new Candidate();
candidate_val = can.CandId;
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
    set { Session["candidate_id_in_session"] = value; }
}
command.Parameters.AddWithValue("@candidate_val",candidate_val ?? DBNull.Value);
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
}
而在新创建的
候选对象
中,未设置
CandId
CandId
的值为
null

另外,
CandId
属性的实现有些奇怪。我会这样实现它:

Candidate can = new Candidate();
candidate_val = can.CandId;
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
    set { Session["candidate_id_in_session"] = value; }
}
command.Parameters.AddWithValue("@candidate_val",candidate_val ?? DBNull.Value);
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
}
否则,您必须调用
CandId=
将会话中的值输入到
CandId
属性中-这有多符合逻辑

作为一名程序员,我希望属性返回当前值,并在设置时更改当前值,这不是您的实现所做的


因为注释中提到了它:要显式地将参数设置为
DBNull
,您需要如下所示:

Candidate can = new Candidate();
candidate_val = can.CandId;
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
    set { Session["candidate_id_in_session"] = value; }
}
command.Parameters.AddWithValue("@candidate_val",candidate_val ?? DBNull.Value);
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
}

更清楚地说:我认为这样实现属性是非常糟糕的风格!如果我打电话

CandId = "Hello";
我希望属性的值为“Hello”,而不是像您的情况那样的其他值


从我得到的评论来看,你甚至不想设置属性。然后您应该像这样修改它:

Candidate can = new Candidate();
candidate_val = can.CandId;
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
    set { Session["candidate_id_in_session"] = value; }
}
command.Parameters.AddWithValue("@candidate_val",candidate_val ?? DBNull.Value);
public String CandId {
    get { return Convert.ToString(Session["candidate_id_in_session"]; }
}

最终编辑

您正在实施的设计没有得到很好的规划。类
Report
实际上独立于任何与UI/web/interaction相关的东西,而是一个纯业务逻辑类。事实上,在ASP.NET、WinForms、WPF或Windows服务项目中使用此类都无关紧要。为什么要通过访问ASP.NET会话引入依赖项?没有理由这样做,也不应该这样做(就像业务逻辑不应该显示错误消息一样)

您应该更改这些方法,以便它们将所需的值作为参数(并且在使用时,适当地释放资源):

如果这样做了,只需调用
LoadReport
函数即可解决问题,如下所示:

DataSet ds = Report.LoadReport(Convert.ToString(Session["candidate_id_in_session"]));

需要注意的一个重要问题是:

您不能在
设置器中指定如下值:

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; }
    }
}

需要注意的一个重要问题是:

您不能在
设置器中指定如下值:

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; }
    }
}

二传手打过电话吗?它不是自动调用的。。。你真的需要叫它!为什么我要显式地调用setter?当我创建类的对象并调用它的方法时,它被调用<代码>候选人can=新候选人()
candidate\u val=can.CandId@user3349973你读过我的答案了吗?我猜你的属性实现错误了。如果您希望通过属性从会话中获取值,那么设置属性是没有意义的,但是应该相应地实现getter@创建对象时,不会自动调用user3349973属性设置器。您的属性设置程序从未被调用,因此候选者的id是