You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过ID从列表获取列数据,实现删除操作日志记录?

如何正确检索数据并完成删除日志的插入操作?

你的代码目前存在几个关键问题:循环内重复查询数据库、SQL语句拼接的风险,以及数据检索方式错误导致无法拿到正确值。我来帮你一步步修正:


1. 优化数据查询:一次性获取所有需要的记录

你现在在foreach循环里每次只查询一个ID对应的记录,这会触发多次数据库请求,效率极低。我们可以一次性把所有目标ID对应的Class记录拉取出来:

var targetRecords = context.Class
    .Where(details => ids.Contains(details.ID))
    .Select(details => new 
    { 
        details.studNumber, 
        details.name, 
        details.lastName 
    })
    .ToList();

这样只需要一次数据库调用,就能拿到所有需要的学生数据,比循环查询高效太多。

2. 避免直接拼接SQL(风险+数据错误)

你当前拼接SQL的方式不仅有严重的SQL注入风险,而且result.Where(...)返回的是一个集合,直接拼到字符串里只会输出类型名称(比如System.Linq.Enumerable+WhereSelectListIterator...),根本拿不到实际的字段值。

推荐用EF的实体操作来插入日志,既安全又符合ORM的设计思路:

首先确保你有对应DeletedStudents表的实体类:

public class DeletedStudent
{
    public string studNumber { get; set; }
    public string name { get; set; }
    public string lastName { get; set; }
    public string DeletedBy { get; set; }
    public DateTime DeletedOn { get; set; }
    public int stage { get; set; }
}

然后修改你的方法:

public static void DeleteFromClass(this Entities context, List<long> ids, string deletedBy)
{
    if (!ids.Any()) return;

    // 批量获取待删除学生的信息
    var targetRecords = context.Class
        .Where(d => ids.Contains(d.ID))
        .Select(d => new 
        { 
            d.studNumber, 
            d.name, 
            d.lastName 
        })
        .ToList();

    // 转换为删除日志实体
    var deletedLogs = targetRecords.Select(record => new DeletedStudent
    {
        studNumber = record.studNumber,
        name = record.name,
        lastName = record.lastName,
        DeletedBy = deletedBy,
        DeletedOn = DateTime.Now,
        stage = 1
    }).ToList();

    // 批量插入日志
    context.DeletedStudents.AddRange(deletedLogs);
    context.SaveChanges();

    // 执行原表的删除操作(你的原代码遗漏了这一步)
    var itemsToDelete = context.Class.Where(d => ids.Contains(d.ID));
    context.Class.RemoveRange(itemsToDelete);
    context.SaveChanges();
}

3. 如果必须用SQL语句:使用参数化查询

如果因为特殊需求必须直接写SQL,一定要用参数化查询来避免注入,同时正确获取字段值:

public static void DeleteFromClass(this Entities context, List<long> ids, string deletedBy)
{
    if (!ids.Any()) return;

    var targetRecords = context.Class
        .Where(d => ids.Contains(d.ID))
        .Select(d => new 
        { 
            d.studNumber, 
            d.name, 
            d.lastName 
        })
        .ToList();

    foreach (var record in targetRecords)
    {
        var insertSql = @"INSERT INTO DeletedStudents (studNumber, name, lastName, DeletedBy, DeletedOn, stage)
                          VALUES (@studNumber, @name, @lastName, @deletedBy, @deletedOn, 1)";

        // 用参数化执行,避免注入,同时确保值正确
        context.Database.ExecuteSqlRaw(insertSql, 
            new SqlParameter("@studNumber", record.studNumber),
            new SqlParameter("@name", record.name),
            new SqlParameter("@lastName", record.lastName),
            new SqlParameter("@deletedBy", deletedBy),
            new SqlParameter("@deletedOn", DateTime.Now));
    }

    // 删除原表记录
    var itemsToDelete = context.Class.Where(d => ids.Contains(d.ID));
    context.Class.RemoveRange(itemsToDelete);
    context.SaveChanges();
}

核心问题总结

  • 你原代码中result.Where(e => e.id == item).Select(...)返回的是集合而非单个值,所以无法拿到正确的字段内容,直接取record.studNumber这类单个属性才是正确的方式。
  • 循环内多次查询数据库是低效的,批量查询才是最优解。
  • 直接拼接SQL存在注入风险,参数化查询或EF实体操作才是安全的做法。

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

火山引擎 最新活动