我有以下代码:
var result = Database.Set<Product>()
.Where(x => x.Product.CreatedAt >= fromDate
&& x.Product.CreatedAt <= toDate);
var group1 = result
.GroupBy(x => new { Id = x.Id, Name = x.Name })
.Select(x => new { Id = x.Key.Id, Name = x.Key.Name });
var group2 = result
.GroupBy(x => new { Id = x.Id, Price = x.Price })
.Select(x => new { Id = x.Key.Id, Name = x.Key.Price });
var group3 = result
.GroupBy(x => new { Id = x.Id, Category = x.Category })
.Select(x => new { Id = x.Key.Id, Name = x.Key.Category });
Run Code Online (Sandbox Code Playgroud)
请不要注意GroupBy条件.假设我需要三组中的数据,以便进一步处理该行.
我假设上面的代码可能会触发至少三个SQL查询来生成结果.这样做会不正确吗?
var result = Database.Set<Product>()
.Where(x => x.Product.CreatedAt >= fromDate
&& x.Product.CreatedAt <= toDate)
.ToList();
Run Code Online (Sandbox Code Playgroud)
此时我假设只有一个SQL调用来获取结果集并将其放在内存中.我进一步假设将在内存集合中执行三个GroupBy操作,而不是激发更多的SQL查询.
我的推理是否正确?这种方法有任何上行/下行吗?
你的推理是正确的,调用ToList()只会通过一个SQL查询将数据拉入本地内存,然后后续的分组和选择操作将仅在本地内存中执行。
由于后续的 Linq 查询只是对数据进行重新排序,因此将其传递给 SQL Server 并以不同的顺序多次下载数据并不会获得太多好处。主要优点是减少客户端的内存占用。如果数据太大,本地机器无法容纳,则必须在 SQL Server 上进行分组,然后分段将其拉至客户端。
如果后续的 Linq 查询进一步过滤数据而不仅仅是重新排序,那么在第一个查询上使用 .ToList 的决定就不那么明确了。第一个查询可能会提取比您需要的更多的数据,这很容易比进行三个查询(每个查询仅提取少量数据)的成本更高。
有利于在一个查询中提取数据并在本地内存中重新排序的另一个因素是三个最终结果集之间的数据一致性。如果您运行 3 个 SQL 查询,由于服务器上同时发生更新,因此每个查询中可能会得到不同的结果。通过拉取数据一次,您可以对数据进行快照,将其与并发更新隔离,从而保证三个分组包含完全相同的数据,只是顺序不同。