Web应用调用T-SQL存储过程异常:SkillId空值与分数错误
技能矩阵表单数据插入问题排查与解决
问题概述
为学习目的搭建简易技能矩阵,通过Web表单调用T-SQL存储过程向SkillLevel表插入5条记录,提交后出现两个问题:
- 仅2条记录插入成功,但分数字段存储的是下拉框的标签文本而非选项值
- 另外3条因
SkillId为空报错:System.Data.SqlClient.SqlException: 'Cannot insert the value NULL into column 'SkillId', table 'testskillsdb.dbo.SkillLevel'; column does not allow nulls. INSERT fails.'
代码片段
ASPX页面代码(示例)
<form id="form1" runat="server"> <div> <label>技能1:</label> <asp:DropDownList ID="ddlSkill1" runat="server"> <asp:ListItem Text="基础" Value="1"></asp:ListItem> <asp:ListItem Text="熟练" Value="2"></asp:ListItem> </asp:DropDownList> <asp:HiddenField ID="hfSkillId1" Value="1" runat="server" /> </div> <div> <label>技能2:</label> <asp:DropDownList ID="ddlSkill2" runat="server"> <asp:ListItem Text="基础"></asp:ListItem> <!-- 未设置Value属性 --> <asp:ListItem Text="熟练"></asp:ListItem> </asp:DropDownList> <asp:HiddenField ID="hfSkillId2" runat="server" /> <!-- 未设置Value --> </div> <!-- 另外3个技能控件类似,可能存在SkillId控件未赋值或缺失 --> <asp:Button ID="btnSubmit" runat="server" Text="提交" OnClick="btnSubmit_Click" /> </form>
C#后台代码(示例)
protected void btnSubmit_Click(object sender, EventArgs e) { List<SkillLevel> skills = new List<SkillLevel> { // 错误:取Text而非Value new SkillLevel { SkillId = int.Parse(hfSkillId1.Value), Score = ddlSkill1.SelectedItem.Text }, new SkillLevel { SkillId = string.IsNullOrEmpty(hfSkillId2.Value) ? 0 : int.Parse(hfSkillId2.Value), Score = ddlSkill2.SelectedValue }, // 错误:hfSkillId3/4/5可能为空或未正确赋值 new SkillLevel { SkillId = int.Parse(hfSkillId3.Value), Score = ddlSkill3.SelectedValue }, new SkillLevel { SkillId = int.Parse(hfSkillId4.Value), Score = ddlSkill4.SelectedValue }, new SkillLevel { SkillId = int.Parse(hfSkillId5.Value), Score = ddlSkill5.SelectedValue } }; using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["TestSkillsDB"].ConnectionString)) { conn.Open(); foreach (var skill in skills) { using (SqlCommand cmd = new SqlCommand("InsertSkillLevel", conn)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@SkillId", skill.SkillId); cmd.Parameters.AddWithValue("@Score", skill.Score); cmd.ExecuteNonQuery(); } } } } public class SkillLevel { public int SkillId { get; set; } public string Score { get; set; } }
T-SQL存储过程(示例)
CREATE PROCEDURE InsertSkillLevel @SkillId INT, @Score NVARCHAR(50) AS BEGIN SET NOCOUNT ON; INSERT INTO SkillLevel (SkillId, Score) VALUES (@SkillId, @Score) END
问题原因
分数值错误:
后台代码获取下拉框值时用了SelectedItem.Text,这会取到下拉框显示的文本内容,而非实际需要存储的选项值,应该用SelectedValue。SkillId为空报错:
- 对应3条记录的
SkillId来源控件(如隐藏域)未设置有效Value值,或者控件ID在后台代码中匹配错误,导致获取到空值。 - 部分SkillId控件可能遗漏了
runat="server"属性,后台无法访问到控件值。 - 未对
SkillId做空值校验,直接将空值传入存储过程,触发表的非空约束报错。
- 对应3条记录的
解决方案
修正分数值获取逻辑:
将后台代码中下拉框值的获取方式从SelectedItem.Text改为SelectedValue,确保插入的是选项值:Score = ddlSkill1.SelectedValue确保SkillId值有效:
- 检查ASPX页面中所有SkillId控件,确认添加了
runat="server"属性,且Value已绑定正确的SkillId数值。 - 后台代码添加空值校验,避免无效记录进入插入流程:
foreach (var skill in skills) { if (skill.SkillId <= 0) // 假设SkillId为正整数 continue; // 或提示用户修正无效项 // 执行插入操作 } - 给存储过程添加参数校验,提前拦截无效值:
CREATE PROCEDURE InsertSkillLevel @SkillId INT, @Score NVARCHAR(50) AS BEGIN SET NOCOUNT ON; IF @SkillId IS NULL OR @SkillId <= 0 BEGIN RAISERROR('无效的SkillId,请传入有效数值', 16, 1); RETURN; END INSERT INTO SkillLevel (SkillId, Score) VALUES (@SkillId, @Score) END
- 检查ASPX页面中所有SkillId控件,确认添加了
内容的提问来源于stack exchange,提问作者Graham Howard
相关产品推荐
相关产品推荐

