C#向存储过程用户定义数据表传递Null值的处理方案问询
解决SQL Server表值参数传递Null的问题
SQL Server的表值参数(TVP)不支持传递DBNull,必须传递结构匹配的DataTable——哪怕是空表,也不能传Null。你的问题出在当输入列表为Null时,直接尝试将其转成DataTable,最终传递了DBNull给存储过程参数。
处理方案
- 替换Null列表为空列表:当
finalinput.ProjectIds或finalinput.AccountIds为Null时,初始化一个空的对应类型列表,再转成DataTable,确保最终传递的是空的结构匹配的DataTable,而非DBNull。 - 避免Null初始化List:直接用Null初始化List会抛出
ArgumentNullException,必须先做Null判断,用空列表替代。
修改后的代码示例
public string SubmitGroupInfo(GroupSettingsInputs finalinput) { string result = string.Empty; // 处理Null列表,替换为空列表 List<ProjectIDinputList> ProjectIdDetails = finalinput.ProjectIds ?? new List<ProjectIDinputList>(); List<AccountIDinputList> AccountIdDetails = finalinput.AccountIds ?? new List<AccountIDinputList>(); DataTable projectlist = ToDataTable(ProjectIdDetails); DataTable accountlist = ToDataTable(AccountIdDetails); dbcmd = this.sqlConn.GetStoredProcCommand("SPName"); dbcmd.CommandType = CommandType.StoredProcedure; dbcmd.CommandTimeout = 240; // 传递空DataTable而非DBNull,符合TVP要求 this.sqlConn.AddParameter(dbcmd,"@ProjectIds",SqlDbType.Structured,projectlist); this.sqlConn.AddParameter(dbcmd,"@AccountIds",SqlDbType.Structured,accountlist); using (IDataReader datareader = this.sqlConn.ExecuteReader(dbcmd)) { while (datareader.Read()) { result = Convert.ToString(datareader["result"]); } } return result; }
额外说明
如果存储过程逻辑需要区分“传递了空列表”和“未传递参数”,可以在存储过程里判断TVP的行数:比如用IF EXISTS(SELECT 1 FROM @ProjectIds)来处理有数据的情况,否则走AccountId的逻辑。
内容的提问来源于stack exchange,提问作者anil websyn
相关产品推荐
相关产品推荐

