2016-04-10 2 views
0

мне нужна помощь, чтобы построить запрос Linq для отображения платежей, сгруппированных по категориям, которые могут быть отфильтрованы по годам, месяцам и имени пользователяLinq Group по 6 Категории и Person

У меня есть эти модели

Member(MemberId,MemberName) 
Payment(PayId, MemberId[foreignkey], PayDate, Amount,CategoryId[foreignkey]) 
Category(CategoryId, CategoryName} 

Глядя на получение выходного сигнала, как показано ниже Джон мог бы сделать два различных платежей для одной и той же категории в апреле месяце (04), и такие платежи суммируются (сумма)

Name Year Month Cat1  Cat2 Cat3 Cat4 Cat5 Cat6 
John 2016 04  12.30 0.00 30.60 15.20 120.00 15.40 
Fred 2016 04  10.30 22.50 80.60 0.00 100.00 19.40 

Я пробовал использовать соединения, но мое приложение для реальной жизни имеет 25 категорий оплаты и присоединение к той же таблице в 25 раз превышает допустимые подвыборы MYSQL на производственном сервере.

Я буду рад получить направление на лучший способ для достижения этой цели

+0

Вы хотите, чтобы это сгруппированных по имени пользователя и год и месяц (т.е. отображать строки для «John 2016 04» и «John 2016 03» и «John 2015 12» и т. д., или просто сгруппированы по имени пользователя и отфильтрованы в течение определенного месяца и года? –

+0

сгруппированы по имени пользователя и отфильтрованы за определенный месяц и год – Diin

+0

ОК, Нет времени только сейчас, но добавит ответ примерно через час. –

ответ

1

Вы указали в комментариях, что вы хотите фильтровать мой месяц/год, так что, кажется, нет необходимости включать эти столбцы в таблице и вместо этого вы можете использовать заголовок для таблицы, например «Результаты за апрель 2016 года».

Начните с определения просмотра моделей для представления хотим, чтобы вы хотите отобразить в представлении

public class MemberPaymentVM // for the table rows 
{ 
    public MemberPaymentVM(int categoryCount) 
    { 
     Amounts = new List<decimal>(new decimal[categoryCount]); 
    } 
    public string Name { get; set; } 
    public List<decimal> Amounts { get; set; } 
    public decimal Total { get; set; } 
} 
public class MonthPaymentsVM 
{ 
    [DisplayFormat(DataFormatString = "{0:MMMM yyyy}"] 
    public DateTime Date { get; set; } 
    public IEnumerable<string> Categories { get; set; } 
    public List<MemberPaymentVM> Payments { get; set; } 
} 

следующие запросы могут быть прикованным, но сломать это в каждом компоненте, первый фильтр данных

var date = new DateTime(2016, 4, 1); 
var filtered = db.Payments.Where(x => x.PayDate >= date && x.PayDate < date.AddMonths(1)); 

Затем группируйте данные как Member, так и Category и суммируйте полученные результаты (я полагаю, что ваша модель Payment содержит виртуальные свойства для отношений

var grouped = filtered.GroupBy(x => new { member = x.Member.ID, category = x.Category.ID }).Select(x => new 
{ 
    Member = x.First().Member, 
    Category = x.First().Category, 
    Amount = x.Sum(y => y.Amount) 
}); 

Затем группа снова Member для представления каждой строки таблицы

var data = grouped.GroupBy(x => x.Member.ID); 

Далее, получить ваши категории

var categories = db.Categories; 
var categoryCount = categories.Count(); 
var categoryIDs = categories.Select(x => x.CategoryId).ToList(); 

И сборки вы просмотра моделей

var model = new MonthPaymentsVM() 
{ 
    Date = date, 
    Categories = categories.Select(x => x.CategoryName), 
    Payments = new List<MemberPaymentVM>() 
}; 
foreach(var group in data) 
{ 
    MemberPaymentVM payment = new MemberPaymentVM categoryCount); 
    payment.Name = group.First().Member.Name; 
    foreach (var item in group) 
    { 
     int index = categoryIDs.IndexOf(item.Category.CategoryId); 
     payment.Amounts[index] = item.Amount; 
     payment.Total += item.Amount; 
    } 
    model.Payments.Add(payment); 
} 

и, наконец, , верните модель на вид

return View(model); 

И по мнению

@model MonthPaymentsVM 
<h2>@Html.DisplayFor(m => m.Date); 
<table> 
    <thead> 
     <tr> 
      <td>Name</td> 
      @foreach(var category in Model.Categories) 
      { 
       <td>@category</td> 
      } 
      <td>Total</td> 
     </tr> 
    </thead> 
    <tbody> 
     @foreach (var item in Model.Payments) 
     { 
      <tr> 
       <td>@item.Name</td> 
       @foreach (var amount in item.Amounts) 
       { 
        <td>@amount</td> // @amount.ToString("c") to format it 
       } 
       <td>@item.Total</td> 
      </tr> 
     } 
    </tbody> 
</table> 
+0

спасибо, что я получаю эту ошибку при var Categories = db.Categories(); Ошибка Не вызывающий вызов элемент не может использоваться как метод. – Diin

+0

Opps, извините - удалите parenthisis - см. Обновление –

+0

Измените его на 'var categoryIDs = categories.Select (x => x.CategoryId) .ToList();' (см. Править) –