C# DataGridView联表查询后获取选中行值报主键缺失错误求助
解决联表查询后DataTable无主键导致的Rows.Find报错问题
问题原因
虽然Assignment表本身定义了主键,但使用多表联合查询后,数据库返回的结果集是多表组合结构,不会向SqlDataAdapter传递主键元数据;同时FillSchema无法自动识别多表结果集的主键,导致DataSet中的Assignment表PrimaryKey属性为空,调用Rows.Find时就会抛出MissingPrimaryKeyException。
解决方案
1. 手动为DataTable设置主键
在填充数据完成后,强制指定AssignmentID列为DataTable的主键,代码修改如下:
daAssignmentDue.Fill(dsStudentManagementSystem, "Assignment"); // 手动设置主键 DataTable assignmentTable = dsStudentManagementSystem.Tables["Assignment"]; assignmentTable.PrimaryKey = new DataColumn[] { assignmentTable.Columns["AssignmentID"] }; // 后续绑定DataGridView的代码不变 dgvAssignmentsDue.DataSource = dsStudentManagementSystem.Tables["Assignment"]; dgvAssignmentsDue.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); dgvAssignmentsDue.Refresh();
此方法直接绕过自动识别主键的问题,确保Rows.Find能正常通过主键值查找行。
2. 移除无效的FillSchema调用(可选)
联表场景下FillSchema无法获取有效主键信息,反而多一次数据库请求,可以直接移除该调用,只保留Fill操作即可,不影响功能。
重要修复:SQL注入漏洞
当前代码使用字符串拼接学生ID,存在严重的SQL注入风险,必须改为参数化查询:
// 改写SQL,使用参数占位符 sqlAssignmentDue = @"SELECT a.AssignmentID, a.AssignmentName AS Name, a.ReleaseDate AS Released, a.DueDate AS Due, a.Submitted, a.Score, asD.ModuleCode, aStu.StudentID FROM Assignment a JOIN AssignmentDetails asD ON a.AssignmentID = asd.AssignmentID LEFT JOIN AssignmentStudents aStu ON a.AssignmentID = aStu.AssignmentID WHERE aStu.StudentID = @StudentID AND a.Submitted = 0"; // BIT类型用数值0代替字符串'false'更稳妥 daAssignmentDue = new SqlDataAdapter(sqlAssignmentDue, connStr); // 添加参数,避免SQL注入 daAssignmentDue.SelectCommand.Parameters.AddWithValue("@StudentID", txtGradeStudentID.Text); // 后续填充数据的代码不变
参数化查询不仅能避免注入攻击,还能避免因特殊字符(如单引号)导致的SQL语法错误。
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

