我有一个用户表,分组为会话。我想为每个用户选择一个数组,其中包含每个会话中的任务数量:
var taskCounts =
from session in gzClasses.e_userLongSessions
orderby session.workerId ascending, session.startTime ascending
group session by session.workerId
into record
select record.Select(s => s.totalTasks).ToArray();
int[][] result = taskCounts.ToArray();
以上理论上可行,但它会为每个用户生成单独的SQL查询,如下图所示。由于数据库不是本地的,因此需要很长时间。有没有办法在一个查询中获取所有数据并减少运行一堆单个查询的开销?
与此同时,我希望通过仅通过线路传输totalTasks
整数值来确保它的效率,而不是发送整个数据库记录。
换句话说,我想在一个查询中从远程数据库中获取一组分组整数,并将它们安排到C#程序中的数组中。原则上这听起来很简单,但我很难让LINQ做到这一点。
答案 0 :(得分:1)
根据您获取的记录数量,您可以返回最少量的数据并在内存中进行分组(很快就会对其进行排序):
使用方法语法:
gzClasses.e_userLongSessions
.OrderBy(s => s.workerId)
.ThenBy(s => s.startTime)
.Select(s => new { s.workerId, s.totalTasks })
.ToList()
.GroupBy(x => x.workerId)
.Select(g => g.Select(x => x.totalTasks).ToArray())
.ToArray();
使用查询语法:
var query = from session in gzClasses.e_userLongSessions
orderby session.workerId ascending, session.startTime ascending
select new { Id = s.workerId, s.totalTasks };
var taskCounts = from worker in query.ToList()
group worker by worker.Id into g
select g.Select(x => x.totalTasks).ToArray();
var result = taskCounts.ToArray();
我在Linqpad中看到了相同的行为(Linq-to-SQL默认值),但我觉得我已经看到Linq-to-Entities处理GroupBy
后跟group.Select(x => x.Something)
而没有得到{{1}}在一个n + 1查询中...虽然可以想象一下(不确定SQL会是什么样子来实现)。
答案 1 :(得分:0)
字典不会比数组数组更有用吗?
gzClasses.e_userLongSessions.OrderBy(s => s.workerId)
.ThenBy(s => s.startTime)
.GroupBy(s => s.workerId, t => t.TotalTasks).ToArray()
.ToDictionary(g => g.Key, h => h.ToArray());
那应该返回一个Dictionary,其中workerId为键,并且任务数量的数组为值。
答案 2 :(得分:-1)
也许如果你从gzClasses.e_userLongSessions"中的会话中替换"来自"来自gzClasses.e_userLongSessions.AsEnumerable()"?
的会话答案 3 :(得分:-2)
ToArray()
的位置导致LINQ比应该更加急切,导致您的许多查询。我认为这只会导致一个查询:
var taskCounts =
from session in gzClasses.e_userLongSessions
orderby session.workerId ascending, session.startTime ascending
group session by session.workerId
into record
select record.Select(s => s.totalTasks);
int[][] result = taskCounts.Select(x => x.ToArray()).ToArray();