如何在EntityFramework 6中编写原生SQL命令?含IN子句删除场景
解决方案
一、参数化原生SQL写法(规避注入+正确处理整数)
你当前的代码存在两个问题:一是WHERE关键字后缺少要匹配的列名(比如Id),二是直接拼接字符串存在SQL注入风险。通过参数化查询可以同时解决这两个问题,确保整数类型正确传递:
public void DeleteRow(List<int> rowIds) { if (!rowIds.Any()) return; // 空列表直接返回,避免无效操作 using (var db = new SkataModel()) { // 生成带索引的参数,如@p0、@p1 var parameters = rowIds.Select((id, index) => new SqlParameter($"@p{index}", id)).ToArray(); // 拼接参数占位符 var placeholders = string.Join(", ", parameters.Select(p => p.ParameterName)); // 构造参数化SQL语句 var sql = $"DELETE FROM db.T0590_CODE_STRING WHERE Id IN ({placeholders})"; // EF6使用ExecuteSqlCommand,EF Core替换为ExecuteSqlRaw db.Database.ExecuteSqlCommand(sql, parameters); } }
这种方式既保证了参数以整数类型传入数据库,又彻底消除了SQL注入风险,比直接字符串拼接更安全可靠。
二、Linq原生写法(简洁易维护)
如果不需要手写原生SQL,直接使用EF的Linq方法更高效:
方法1:先查询再删除(适用于数据量较小的场景)
public void DeleteRow(List<int> rowIds) { if (!rowIds.Any()) return; using (var db = new SkataModel()) { var targetEntities = db.T0590_CODE_STRING.Where(x => rowIds.Contains(x.Id)); db.T0590_CODE_STRING.RemoveRange(targetEntities); db.SaveChanges(); } }
方法2:直接执行删除(EF Core 7+支持,无需查询实体)
如果数据量较大,不想先加载实体到内存,可以用ExecuteDelete直接在数据库执行删除:
public void DeleteRow(List<int> rowIds) { if (!rowIds.Any()) return; using (var db = new SkataModel()) { db.T0590_CODE_STRING.Where(x => rowIds.Contains(x.Id)).ExecuteDelete(); // 无需调用SaveChanges,ExecuteDelete直接操作数据库 } }
三、关于你原写法的补充说明
你之前用string.Join拼接的方式,最终生成的SQL里虽然是数字格式(int转字符串后为"1,2,3",SQL会自动识别为整数),但这种写法存在严重的SQL注入风险,如果rowIds被恶意篡改,可能导致数据库被攻击,因此强烈不建议使用。参数化查询或Linq方法才是合规的解决方案。
内容的提问来源于stack exchange,提问作者Bouyalife
相关产品推荐
相关产品推荐

