ClassID传值为空求助:调试时ClassID值丢失排查
我最近碰到一个棘手的问题:调试断点里明明能看到ClassID被正确传递,但当程序获取我创建的学生列表时,对应断点里的ClassID却变成null了。我怀疑问题出在控制器或数据访问层,但一直找不到具体原因,麻烦各位大佬帮忙分析排查!
相关代码
数据访问层(DB文件)
public DataSet GetClass(string ClassID) { ClassModel classes = new ClassModel(); SqlCommand com = new SqlCommand("sp_ABEAttendanceEnrollment", ABEAttendanceDB); com.CommandType = CommandType.StoredProcedure; com.Parameters.AddWithValue("@ClassID", ClassID); SqlDataAdapter da = new SqlDataAdapter(com); DataSet ds1 = new DataSet(); da.Fill(ds1); return ds1; } public IEnumerable<ClassModel> ClassModel { get { string connectionString = ConfigurationManager.ConnectionStrings["ABEAttendanceDB"].ConnectionString; List<ClassModel> students = new List<ClassModel>(); using (SqlConnection con = new SqlConnection(connectionString)) { ClassModel classes = new ClassModel(); SqlCommand cmd = new SqlCommand("sp_ABEAttendanceEnrollment", ABEAttendanceDB); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@ClassID", classes.ClassID); SqlDataAdapter da = new SqlDataAdapter(cmd); DataSet ds1 = new DataSet(); da.Fill(ds1); ABEAttendanceDB.Open(); SqlDataReader rdr = cmd.ExecuteReader(); while (rdr.Read()) { ClassModel student = new ClassModel(); student.ClassID = rdr["ClassID"].ToString(); student.SID = rdr["SID"].ToString(); student.FullName = rdr["FullName"].ToString(); students.Add(student); } ABEAttendanceDB.Close(); return students; } } }
控制器代码
public class ClassController : Controller { DAL.DB dblayer = new DAL.DB(); public ActionResult Class(ClassModel ClassModel) { DataSet ds1 = dblayer.GetClass(ClassModel.ClassID); ViewBag.general = ds1.Tables; ViewBag.Message = TempData["Message"]; DB classes = new DB(); List<ClassModel> students = dblayer.ClassModel.ToList(); return View(); } }
排查及解决建议
我一眼就看到了几个关键问题,按优先级给你列出来:
ClassModel属性的致命逻辑错误
在ClassModel属性的getter里,你新建了一个空的ClassModel实例,这个实例的ClassID默认是null,然后你直接把这个null传给了存储过程的@ClassID参数——这就是列表获取时ClassID为空的根本原因!
解决办法:把这个属性改成带参数的方法,接收控制器传来的正确ClassID,比如:public IEnumerable<ClassModel> GetStudentsByClassID(string classID) { string connectionString = ConfigurationManager.ConnectionStrings["ABEAttendanceDB"].ConnectionString; List<ClassModel> students = new List<ClassModel>(); using (SqlConnection con = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand("sp_ABEAttendanceEnrollment", con); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@ClassID", classID); con.Open(); SqlDataReader rdr = cmd.ExecuteReader(); while (rdr.Read()) { ClassModel student = new ClassModel(); student.ClassID = rdr["ClassID"].ToString(); student.SID = rdr["SID"].ToString(); student.FullName = rdr["FullName"].ToString(); students.Add(student); } con.Close(); return students; } }然后在控制器里调用这个方法:
List<ClassModel> students = dblayer.GetStudentsByClassID(ClassModel.ClassID).ToList();数据库连接的不规范使用
在ClassModel属性里,你同时混用了SqlDataAdapter和SqlDataReader,还直接操作全局的ABEAttendanceDB连接,这很容易导致连接泄漏或操作冲突。建议统一用一种数据读取方式,并且始终在using块内管理连接,避免依赖全局连接对象。控制器冗余代码清理
控制器里你新建了DB classes = new DB();但完全没用到,直接删掉即可,减少代码冗余。调试技巧补充
下次调试时,在ClassModel属性的getter里设置断点,查看classes.ClassID的值,就能直观看到它是null的状态;也可以在存储过程里加日志输出,确认传入的@ClassID参数值,辅助快速定位问题。
内容的提问来源于stack exchange,提问作者DilbarC

