简体   繁体   中英

Group By Linq ASP.NET

I currently display a list of errors from a database. As you can see from the image below, there are a number of errors that share the same Application Name. 在此处输入图片说明

I am wanting to group all the errors with the same name together and just show the one error with that application name instead of all of them.

I have looked at other questions on here related to what I am doing but none of them have given me the answer I require.

This is my current code.

Controller

public ActionResult Index(string sortOrder, string searchString, string currentFilter, int? page)
    {
        ViewBag.CurrentSort = sortOrder;
        ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";

        if (searchString != null)
        {
            page = 1;
        }
        else
        {
            searchString = currentFilter;
        }

        ViewBag.CurrentFilter = searchString;

        var applications = from s in db.ElmahErrors
                     select s;


        if (!String.IsNullOrEmpty(searchString))
        {
            applications = applications.Where(s => s.Application.Contains(searchString));
        }

        switch (sortOrder)
        {
            default:
                applications = applications.OrderBy(x => x.Application).ThenByDescending(s => s.TimeUtc);
                break;
        }


        int pageSize = Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["DefaultPageSize"]);
        int pageNumber = (page ?? 1);
        return View(applications.ToPagedList(pageNumber, pageSize));
    }  

View

@model PagedList.IPagedList<DataIntelligence.Models.ElmahError>
@using PagedList.Mvc;
<link href="Content/PagedList.css" rel="stylesheet" type="text/css" />

@{
    ViewBag.Title = "Application Error Dashboard";
}

<div class="jumbotron">
    <h2>Application Error Dashboard</h2>
</div> 
@using (Html.BeginForm("Index", "Application", FormMethod.Get))
{
    <p>
        Find by Application: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
        <input type="submit" value="Search" />
    </p>
}
<table>
    <tr>
        <th>
            Application
        </th>
        <th>
            Host
        </th>
        <th>
            Type
        </th>
        <th>
           Date
        </th>
        <th>
            Message
        </th>

    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            <a href="@Url.Action("Details", new { id=item.ErrorId})"> @Html.DisplayFor(modelItem => item.Application) </a>      
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Host)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Type)

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


    </tr>
}

</table>
<br />
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of     @Model.PageCount

@Html.PagedListPager(Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))  

How would I go about changing this code in order to achieve what I am wanting?

Thanks in advance.

If you replace:

var applications = from s in db.ElmahErrors
                 select s;

With:

var applications = db.ElmahErrors
  .GroupBy(s => s.Application)
  .Select(grp => grp.FirstOrDefault());

Then the query will only deal with one element for each application.

You might also wish to do this grouping at a later state, if there were elements in ElmahErrors you wanted to filter out, on some other criteria, to make sure you didn't happen to filter out the distinct item chosen when there was another item with the same Application that wouldn't have been filtered.

You should take a look at 'MoreLinq', perhaps their DistinctBy provides the answer you need. It is available in NuGet. MoreLINQ's DistinctBy for C#

Should work something like this:

List<ElmahErrors> distinctByError = db.ElmahErrors.DistinctBy(x => x.Message).ToList();

Try this query

var applications = from s in db.ElmahErrors
 group c by new
    {
        s.Application,
        s.Host,
        s.Type, 
        s.Date,
        s.Message
    } into gcs
    select new ElmahErrors()
    {
        gcs.key.Application,
        gcs.key.Host,
        gcs.key.Type, 
        gcs.key.Date,
        gcs.key.Message
    };
var results = from a in applications
              group a by a.Application into g
              select new { Application = g.Key, Count = g.Count(), LastDate = g.Max(d=>d.Date) };

Or if you want to group by more coulms:

 var results = from a in applications
                  group a by new {a.Application, a.Message} into g
                  select new { Application = g.Key.Application, Message = g.Key.Message, Count = g.Count(), LastDate = g.Max(d=>d.Date) };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM