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

使用DataTable作为存储过程参数插入数据时遇EventDateTime非空错误

问题描述

使用C#将DataTable作为SQL Server存储过程参数插入数据时,触发异常:

Cannot insert the value NULL into column 'EventDateTime', table ABC column does not allow nulls. INSERT fails.
The statement has been terminated.

以下是相关代码:

SQL 表、自定义表类型及存储过程代码

create table ABC(
[S] nvarchar(50) Not NULL,
[Type] nvarchar(50) Not NULL,
[R] nVarchar(50) Not NULL,
[C] int Not NULL,
[EventDateTime] datetime NOT NULL,
CONSTRAINT [pk_chillerstatus] 
PRIMARY KEY CLUSTERED ([S] ASC, [Type] ASC, [R] ASC, [EventDateTime])
);


CREATE TYPE [dbo].[ABCType] AS TABLE (
[S] nvarchar(50),
[Type] nvarchar(50),
[R] nVarchar(50),
[C] int 
,[EventDateTime] datetime
);

create procedure [dbo].[spInsertABC]
(
@abc [dbo].[ABCType] READONLY
)
as
begin

INSERT INTO ABC(S, Type,R,C
,EventDateTime
) 
     SELECT p.S, p.Type,p.R,p.C
     ,p.EventDateTime
     FROM @abc p;
end;

C# 生成DataTable代码

public DataTable GenerateDatatable(DateTime eventDateTime, string s)
 {
     DataTable dt = new DataTable();
     dt.Columns.Add("S", typeof(string));
     dt.Columns.Add("Type", typeof(string));
     dt.Columns.Add("R", typeof(string));
     dt.Columns.Add("C", typeof(int));
     dt.Columns.Add("EventDateTime", typeof(DateTime));
     
    dt.Rows.Add(s, "E", "A", 0, eventDateTime);
    dt.Rows.Add(s, "E", "M", 2, eventDateTime);
    dt.Rows.Add(s, "E", "N", 3, eventDateTime);
    dt.Rows.Add(s, "E", "S", 4, eventDateTime);
    dt.Rows.Add(s, "E", "No", 5, eventDateTime);
  
    return dt;
 }

C# 调用存储过程代码

public async Task AddABC()
 {
     try
     {
         DateTime eventDatetime = DateTime.Now;

         DataTable rdt = GenerateDatatable(eventDatetime, "R");

         using (SqlConnection con = new SqlConnection(devSqlConnectionString))
         {
             using (var com = new SqlCommand("[dbo].[spInsertABC]", con))
             {
                 con.Open();
                 com.CommandType = CommandType.StoredProcedure;
                 com.CommandTimeout = 500;
                 SqlParameter sqlparam = new SqlParameter("@abc", rdt);
                 sqlparam.SqlDbType = SqlDbType.Structured;
                 sqlparam.TypeName = "dbo.ABCType";
                 com.Parameters.Add(sqlparam);
                 com.ExecuteNonQuery();
             }
         }
     }
     catch (Exception ex)
     {
         throw ex;
    }
 }
解决方案

1. 同步自定义表类型与目标表的列约束

当前自定义表类型ABCType的列未设置NOT NULL约束,而目标表ABC的EventDateTime列不允许为空。修改ABCType,让其列约束与ABC表保持一致:

DROP TYPE IF EXISTS [dbo].[ABCType];
CREATE TYPE [dbo].[ABCType] AS TABLE (
[S] nvarchar(50) NOT NULL,
[Type] nvarchar(50) NOT NULL,
[R] nVarchar(50) NOT NULL,
[C] int NOT NULL,
[EventDateTime] datetime NOT NULL
);

这样可以确保传入的表参数中不会出现NULL值,从源头避免插入失败。

2. 强制DataTable列不允许为空

在C#生成DataTable时,设置EventDateTime列的AllowDBNull为false,确保添加行时必须赋值:

dt.Columns.Add("EventDateTime", typeof(DateTime)).AllowDBNull = false;

如果后续代码中出现未赋值的情况,会在C#层面直接报错,而不是传到SQL Server触发异常。

3. 验证DataTable中的数据

在调用存储过程前,添加代码验证DataTable的每一行EventDateTime是否有值,排查数据是否在生成过程中丢失:

foreach(DataRow row in rdt.Rows)
{
    if(row.IsNull("EventDateTime"))
    {
        throw new InvalidOperationException("EventDateTime字段不能为空");
    }
}

4. 存储过程中增加NULL过滤(临时方案)

如果暂时无法修改表类型,可以在存储过程的插入语句中过滤掉EventDateTime为NULL的行,避免插入失败:

INSERT INTO ABC(S, Type,R,C,EventDateTime) 
SELECT p.S, p.Type,p.R,p.C,p.EventDateTime
FROM @abc p
WHERE p.EventDateTime IS NOT NULL;

内容的提问来源于stack exchange,提问作者prasanthi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:10:28