C#将DataTable传入存储过程(用户自定义表类型插入)出现转换错误
问题原因与修复方案
核心问题1:C#代码读取Excel值未做类型适配
ClosedXML 读取空单元格时返回的是空字符串而非DBNull.Value,且数字单元格可能因Excel格式问题返回字符串类型的数值,直接赋值给声明为decimal类型的DataTable列就会触发类型转换异常。
另外你当前代码调用了两次ImportExceltoDataTable,存在冗余性能开销,同时传参时未明确指定表类型参数的属性,可能导致SQL端类型识别错误。
C#代码修复
修改ImportExceltoDataTable方法中的循环赋值逻辑:
for (int dtRow = 0; dtRow < br_Row - tl_Row; dtRow++) { currentRow = ws.Row(tl_Row + dtRow + 1); var newRow = dt.NewRow(); for (int dtCol = 0; dtCol < dt.Columns.Count; dtCol++) { var cell = currentRow.Cell(tl_Col + dtCol); // 空值统一处理为DBNull if (cell.IsEmpty || string.IsNullOrWhiteSpace(cell.Value?.ToString())) { newRow[dtCol] = DBNull.Value; continue; } // 数字列做强制转换 if (dt.Columns[dtCol].DataType == typeof(decimal)) { if (decimal.TryParse(cell.Value.ToString().Trim(), out decimal num)) { newRow[dtCol] = num; } else { // 可根据业务需求调整为默认值赋值逻辑 throw new FormatException($"Excel第{currentRow.RowNumber()}行第{dtCol+1}列内容不是合法数值"); } } else { // 文本列直接转字符串去空格 newRow[dtCol] = cell.Value.ToString().Trim(); } } dt.Rows.Add(newRow); }
调整存储过程参数的声明逻辑:
var param = new SqlParameter("@trips", SqlDbType.Struct) { TypeName = "dbo.udtTripsPerMonth", Value = dt }; cmd.Parameters.Add(param);
核心问题2:存储过程UPDATE语句字段取值错误
你tblMVAkoder表的ID字段是nvarchar类型,存储的是MVAkode2这类字符串值,而你更新OppdragsMVAkode(decimal类型)时取的是ID字段,自然会触发nvarchar转numeric的报错,你实际要取的是同表的MVAsats(decimal类型的税率字段)。
存储过程优化
可以直接在INSERT阶段就赋值,省去后续两次UPDATE的开销:
ALTER PROCEDURE [dbo].[spGetTrips] @trips udtTripsPerMonth readonly AS BEGIN INSERT INTO tblTripsPerMonth SELECT [KjøretøyID], SUBSTRING([År], 7, 4), SUBSTRING([Måned], 4, 2), [Betaling (brutto)], [Betaling (netto)], [Bestillingsgebyr (netto)], [Betalingsgebyr (netto)], -- 直接从税率表取十进制的税率值赋值 (SELECT [MVAsats] FROM [tblMVAkoder] WHERE [ID] = 'MVAkode2'), CONCAT(LøyvehaverFakturaID, + 'UF-' + SUBSTRING([År], 9, 2) + SUBSTRING([Måned], 4, 2)), [Oppdragsgebyr (netto)], (SELECT [MVAsats] FROM [tblMVAkoder] WHERE [ID] = 'MVAkode5'), CONCAT([RidelRegionFakturaID], + 'UF-' + SUBSTRING([År], 9, 2) + SUBSTRING([Måned], 4, 2)) FROM @trips END
内容的提问来源于stack exchange,提问作者Ole M
相关产品推荐
相关产品推荐

