批量删除/更新时的 LINQ to SQL 陷阱与正确思路

当你把 List<int>(本地内存集合)和 Table<T>(数据库表)做 join 时,LINQ to SQL 无法把本地集合翻译为 SQL 参数,只能选择把数据库表全量拉到内存,再在客户端做关联。


代码

var idstring = "1,2,4";
var ids = idstring.Split(',').Select(m => Convert.ToInt32(m)).ToList();

using (var db = new DataClasses1DataContext())
{
    var q = from i in ids.AsQueryable()        // ← 本地 List<int>
            join s in db.Student               // ← 数据库表
            on i equals s.id
            select s;

    var list = q.ToList();                     // ← 触发执行
}Code language: JavaScript (javascript)

生成的 SQL:

SELECT [t0].[id], [t0].[name], [t0].[age], [t0].[sex]
FROM [dbo].[Student] AS [t0]Code language: CSS (css)

为什么反过来写也一样

var q = from s in db.Student
        join i in ids.AsQueryable()
        on s.id equals i
        select s;Code language: JavaScript (javascript)

结果完全一样——全表拉取,内存关联。

正确方案:Contains 方法

var idstring = "1,2,4";
var ids = idstring.Split(',').Select(m => Convert.ToInt32(m)).ToList();

using (var db = new DataClasses1DataContext())
{
    var list = db.Student
                  .Where(s => ids.Contains(s.id))
                  .ToList();
}Code language: JavaScript (javascript)

生成的 SQL:

SELECT [t0].[id], [t0].[name], [t0].[age], [t0].[sex]
FROM [dbo].[Student] AS [t0]
WHERE [t0].[id] IN (1, 2, 4)Code language: CSS (css)

只查需要的记录,ID 作为参数传入,数据库端过滤。


批量更新写法

public bool HandleInfo(string ids, int type)
{
    try
    {
        var idList = ids.Split(',').Select(m => Convert.ToInt32(m)).ToList();

        var list = db.XX
                      .Where(jf => idList.Contains(jf.id))
                      .ToList();

        foreach (var item in list)
        {
            item.zt = type == 1;
        }

        db.SubmitChanges();
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}Code language: PHP (php)

生成的 SQL:

-- 查询
SELECT * FROM [dbo].[XX] WHERE [id] IN (1, 2, 4)

-- 更新(逐条)
UPDATE [dbo].[XX] SET [zt] = 1 WHERE [id] = 1
UPDATE [dbo].[XX] SET [zt] = 1 WHERE [id] = 2
UPDATE [dbo].[XX] SET [zt] = 1 WHERE [id] = 4

SubmitChanges 会逐条生成 UPDATE,ID 多时考虑用 ExecuteCommand 批量更新。


大量 ID 时的批量更新(ExecuteCommand)

var idstring = "1,2,4";
var sql = $"UPDATE XX SET zt = 1 WHERE id IN ({idstring})";
db.ExecuteCommand(sql);Code language: JavaScript (javascript)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注