You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 20:06:05