JimB_ Ответов: 2

Как использовать groupby data in view для отображения результата в C#, MVC, LINQ


Всем привет

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

Таблица UserRecords
+-------+------+--------------+
|Id     | Name | Cost         |
+-------+------+--------------+
|   1   | Anna |   30.3       |
+-------+------+--------------+
|   2   | Anna |   500        |
+-------+------+--------------+
|   3   | Sam  |   30.3       |
+-------+------+--------------+
|   4   | Tom  |   20.5       |
+-------+------+--------------+
|   5   | Tom  |   20.5       |
+-------+------+--------------+
|   6   | Anna |   20.5       |
+-------+------+--------------+


desire result how to display in web page MVC

Anna  550.8  
Sam    30.3
Tom    41

Total 622.1

Thank you ;)


Что я уже пробовал:

public ActionResult Index()
{
  //Disply user and cost 
  var userNameGroup = db.UserRecords.GroupBy(c=>c.Name);
 foreach (var group in userNameGroup)
   {
                var result = ("{0} -{1}", group.Key, group.Max(s => s.Cost));
   }

 return View(db.UserRecords.GroupBy(x=>x.UserNames).ToList());
        }

//how to go from this to the webpage display


@model IEnumerable<MobileReports.Models.UserRecord>
<table class="table">
    @if (!Model.Any())
    {
        @Html.LabelForModel("Not data uploaded yet")
    }
    else
    {
        <tr>

            
            <th>
                @Html.DisplayNameFor(model => model.Cost)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>

           
            <th></th>
        </tr>

        foreach (var item in Model)
        {
            <tr>
                
                <td>
                    @Html.DisplayFor(modelItem => item.Cost)
                </td>

                <td>
                    @Html.DisplayFor(modelItem => item.Name)
                </td>

               
                <td>                  
                    @Html.DisplayFor(modelItem => item.Total)
                </td>
            </tr>
        }
    }

</table>

Maciej Los

Какая версия MVC? MVC 3, MVC 4, MVC для Core .NET?

2 Ответов

Рейтинг:
12

Richard Deeming

Ваш взгляд ожидает, что модель будет IEnumerable<UserRecord>, но ваше действие проходит мимо IEnumerable<IGrouping<string, UserRecord>> Вам нужно сделать так, чтобы типы совпадали.

Одним из простых вариантов было бы сгруппировать записи в представлении:

public ActionResult Index()
{
    return View(db.UserRecords.ToList());
}
@model IEnumerable<MobileReports.Models.UserRecord>
@if (!Model.Any())
{
    <p>No data uploaded yet.</p>
}
else
{
    <table>
    <thead>
    <tr>
        <th scope="col">Name</th>
        <th scope="col">Cost</th>
    </tr>
    </thead>
    <tfoot>
    <tr>
        <th scope="row">Total:</th>
        <td>@Html.DisplayFor(m => m.Sum(u => u.Cost))</td>
    <tr>
    </tfoot>
    <tbody>
    @foreach (var item in Model.GroupBy(u => u.Name, (key, items) => new { Name = key, Cost = items.Sum(u => u.Cost) }))
    {
        <tr>
            <th scope="row">@Html.DisplayFor(_ => item.Name)</th>
            <th scope="row">@Html.DisplayFor(_ => item.Cost)</th>
        </tr>
    }
    </tbody>
    </table>
}

Более чистым подходом было бы создание модели представления для представления сгруппированных результатов. Заполните модель представления в действии и измените представление, чтобы использовать модель представления.
public class UserCostsViewModel
{
    public string Name { get; set; }
    public decimal Cost { get; set; }
}

public class GroupedUserCostsViewModel
{
    public IReadOnlyList<UserCostsViewModel> Items { get; set; }
    public decimal Total { get; set; }
}
public ActionResult Index()
{
    var source = db.UserRecords.ToList();
    
    var items = source
        .GroupBy(u => u.Name, (key, items) => new UserCostsViewModel
        {
            Name = key,
            Cost = items.Sum(u => u.Cost)
        })
        .ToList();
    
    var model = new GroupedUserCostsViewModel
    {
        Items = items,
        Total = source.Sum(u => u.Cost)
    };
    
    return View(model);
}
@model GroupedUserCostsViewModel
@if (!Model.Items.Any())
{
    <p>No data uploaded yet.</p>
}
else
{
    <table>
    <thead>
    <tr>
        <th scope="col">Name</th>
        <th scope="col">Cost</th>
    </tr>
    </thead>
    <tfoot>
    <tr>
        <th scope="row">Total:</th>
        <td>@Html.DisplayFor(m => m.Total)</td>
    <tr>
    </tfoot>
    <tbody>
    @foreach (var item in Model.Items)
    {
        <tr>
            <th scope="row">@Html.DisplayFor(_ => item.Name)</th>
            <th scope="row">@Html.DisplayFor(_ => item.Cost)</th>
        </tr>
    }
    </tbody>
    </table>
}


Maciej Los

Ой... Я пропустил твой ответ раньше...
5ed!

Рейтинг:
0

Maciej Los

Я бы предложил создать другую модель TotalUserData

public class TotalUserData
{
    public string Name
    {
        get;
        set;
    }

    public double TotalCost
    {
        get;
        set;
    }
}

и контроллер для вышеуказанной модели.

Затем...

public ActionResult Index()
{
  //Display user and cost 
  var userNameGroup = db.UserRecords
        .GroupBy(c=>c.Name)
        .Select(grp=> new TotalUserData(Name=grp.Key, Total=grp.Sum(x=>x.Cost)))
        .ToList();

  return View(userNameGroup);
}


Наконец, перемены View чтобы иметь возможность отображать соответствующие данные.

@model IEnumerable<MvcApplication1.Models.TotalUserData>

@{
    ViewBag.Title = "Total";
}

<h2>Total</h2>
<table class="table">
    @if (!Model.Any())
    {
        @Html.LabelForModel("Not data uploaded yet")
    }
    else
    {
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.TotalCost)
            </th>
            @*<th>Action</th>*@
        </tr>

        foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Name)
                </td>
                <td>                  
                    @Html.DisplayFor(modelItem => item.TotalCost)
                </td>
            </tr>
        }
        <tr><td colspan="2">Total of total: @Model.Sum(x=>x.TotalCost)</td></tr>
    }
</table>