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
相关产品推荐
相关产品推荐

