当你把 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)
Previous: 查询结果与实体类绑定
Next: linq执行增删改查的sql