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

SQL Server插入数据时如何忽略类中Null属性?类比MongoDB的BsonIgnoreIfNull

实现SQL Server插入时忽略Null属性的几种方案

嘿,这个需求我太熟悉了——想要像MongoDB的[BsonIgnoreIfNull]那样,在往SQL Server插数据时自动跳过值为Null的属性。下面根据你常用的数据库访问框架,给你几个实用的实现方式:

方案1:用Dapper(轻量ORM)

Dapper本身就支持动态参数,你只需要把对象转换成只包含非Null属性的参数集合,生成的INSERT语句就只会包含有值的列:

public void InsertEntity(a entity)
{
    var parameters = new DynamicParameters();
    
    // 只添加非Null的属性到参数集合
    if (entity.a != null)
        parameters.Add("@a", entity.a);
    parameters.Add("@b", entity.b);
    parameters.Add("@c", entity.c);
    
    // 动态拼接INSERT语句的列名和参数占位符
    var columns = string.Join(", ", parameters.ParameterNames.Select(p => p.TrimStart('@')));
    var values = string.Join(", ", parameters.ParameterNames);
    var sql = $"INSERT INTO YourTable ({columns}) VALUES ({values})";
    
    using (var connection = new SqlConnection("YourConnectionString"))
    {
        connection.Execute(sql, parameters);
    }
}

方案2:用Entity Framework Core

EF Core默认会把所有属性都包含在INSERT语句里,要实现忽略Null属性,有两种实用思路:

子方案2.1:手动构建参数化插入语句

直接用EF Core的ExecuteSqlRaw执行动态拼接的SQL,确保参数化避免注入风险:

using (var context = new YourDbContext())
{
    var columnList = new List<string>();
    var valuePlaceholders = new List<string>();
    var parameters = new List<SqlParameter>();
    
    if (entity.a != null)
    {
        columnList.Add("a");
        valuePlaceholders.Add("@a");
        parameters.Add(new SqlParameter("@a", entity.a));
    }
    columnList.Add("b");
    valuePlaceholders.Add("@b");
    parameters.Add(new SqlParameter("@b", entity.b));
    
    columnList.Add("c");
    valuePlaceholders.Add("@c");
    parameters.Add(new SqlParameter("@c", entity.c));
    
    var sql = $"INSERT INTO YourTable ({string.Join(",", columnList)}) VALUES ({string.Join(",", valuePlaceholders)})";
    context.Database.ExecuteSqlRaw(sql, parameters.ToArray());
}

子方案2.2:自定义扩展方法筛选非Null属性

利用EF Core的元数据获取实体属性,筛选出非Null的属性构建临时实体再插入:

public static void AddWithIgnoreNull<T>(this DbSet<T> dbSet, T entity) where T : class
{
    var entityType = dbSet.EntityType;
    // 筛选出值不为Null的属性
    var validProperties = entityType.GetProperties()
        .Where(p => p.GetGetter().GetClrValue(entity) != null)
        .ToList();
    
    // 创建临时实体,只赋值非Null属性
    var tempEntity = Activator.CreateInstance<T>();
    foreach (var prop in validProperties)
    {
        prop.GetSetter().SetClrValue(tempEntity, prop.GetGetter().GetClrValue(entity));
    }
    
    dbSet.Add(tempEntity);
}

注意:如果你的实体有必填属性,需要确保临时实体满足验证规则,可根据实际情况调整筛选逻辑。

方案3:无ORM场景(直接用SqlCommand)

如果不用任何ORM,直接用原生SqlCommand的话,核心思路还是动态筛选非Null属性,构建参数化SQL:

public void InsertWithoutORM(a entity)
{
    var columns = new List<string>();
    var parameters = new List<SqlParameter>();
    
    if (entity.a != null)
    {
        columns.Add("a");
        parameters.Add(new SqlParameter("@a", entity.a));
    }
    columns.Add("b");
    parameters.Add(new SqlParameter("@b", entity.b));
    columns.Add("c");
    parameters.Add(new SqlParameter("@c", entity.c));
    
    var sql = $"INSERT INTO YourTable ({string.Join(", ", columns)}) VALUES ({string.Join(", ", parameters.Select(p => p.ParameterName))})";
    
    using (var conn = new SqlConnection("YourConnectionString"))
    {
        conn.Open();
        using (var cmd = new SqlCommand(sql, conn))
        {
            cmd.Parameters.AddRange(parameters.ToArray());
            cmd.ExecuteNonQuery();
        }
    }
}

重要提示

不管用哪种方案,绝对要避免直接拼接属性值到SQL字符串里,一定要用参数化查询防止SQL注入——上面所有例子都严格遵循了这个原则,可以放心使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:50:08