Вы не сможете использовать LINQ to SQL для выполнения всего запроса, потому что каждый столбец соответствует свойству в типе результата и существует неизвестное количество столбцов, поэтому нет способа определить результат тип. Что я сделал в подобных ситуациях, как это определить тип вроде этого:
public class PseudoPivotRow
{
public string RM {get; set;}
public string DM {get; set;}
public int Loc {get; set;}
public string City {get; set;}
public Dictionary<DateTime, int> CountsByDate{get; set}
}
CountsByDate
Свойство соответствует нескольким столбцам даты в шарниром вы хотите создать, с ключом, соответствующий заголовок столбца, а значение значения в ячейке. Вы должны заполнить словарь в два этапа, потому что вы не можете создать Dictionary<T,U>
в запросе LINQ to SQL.
var materializedGroups =
db.SourceTable
.GroupBy(s => new { s.RM, s.DM, s.LocationNum, s.City },
s => new { s.Dates, s.Count })
.ToList();
ToList
заставляет запрос будет выполняться, так что следующая часть происходит на стороне клиента (C#) на стороне, где мы можем проецировать в словарь:
var pivotResult =
materializedGroups
.Select(mg => new PseudoPivotRow
{
RM = mg.Key.RM,
DM = mg.Key.DM,
Loc = mg.Key.LocationNum,
CountsByDate = mg.GroupBy(r => r.Dates, r => r.Count)
.ToDictionary(g => g.Key, g => g.Sum())
};
(Вы можете сделать группировку из дат/подсчетов в первом запросе, если вы захотите, я думаю, что это намного проще написать таким образом, но производительность может быть хуже.)
Недостатком этого шаблона является то, что каждая «строка» в «поворотнике», может иметь различное количество столбцов, а порядок не определен. Если вам нужна согласованность, одна простая опция - получить список всех дат, затем перебрать pivotResult
и вставить 0 для каждой даты, не содержащейся в словаре.