我有以下代码:
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 });
请不要注意GroupBy条件。假设我需要三组中的数据进行进一步的处理。
我假设上面的代码可能会触发至少三个SQL查询来生成结果。这样做会不正确吗?
var result = Database.Set<Product>()
.Where(x => x.Product.CreatedAt >= fromDate
&& x.Product.CreatedAt <= toDate)
.ToList();
此时我假设只有一个SQL调用来获取结果集并将其放在内存中。我进一步假设将在内存集合中执行三个GroupBy操作,而不是发出更多SQL查询。
我的推理是否正确?这种方法有任何上行/下行吗?
答案 0 :(得分:1)
您的推理是正确的,调用ToList()会将数据拉入本地内存,只有一个SQL查询,然后后续的组和选择操作将仅在本地内存中执行。
由于您后续的Linq查询只是重新排序数据,因此将其传递给SQL服务器并以不同的顺序多次下载数据并没有太多好处。主要优点是减少客户端的内存占用。如果数据太大而无法放在本地计算机上,那么您必须在SQL服务器上进行分组并将其分段下载到客户端。
如果后续的Linq查询进一步过滤数据而不仅仅是重新排序,那么在第一个查询中使用.ToList的决定就不那么明确了。第一个查询可以提取比您需要的数据更多的数据,这可能比制作三个只减少每个数据的查询更加昂贵。
支持在一个查询中提取数据并在本地存储器中重新排序的另一个因素是三个最终结果集之间的数据一致性。如果运行3个SQL查询,则由于服务器上同时发生更新,每个查询可能会得到不同的结果。通过将数据向下拉一次,您可以对数据进行快照,将其与并发更新隔离,并确保三个分组按不同顺序包含完全相同的数据。
答案 1 :(得分:0)
回答你的问题:是的。你的推理是正确的。好处是你打了一次DB,而不是4次。缺点取决于您拥有的数据量。对于相对较小的结果集,确实没有缺点。
但是,当Adam评论你的问题时,你真的应该尝试两种方式并使用Stopwatch
类对它们进行分析。