Reputation: 429
I have a dashboard that shows an updated list of application errors. Some errors have happened more than once so I have grouped them by their error type and placed a count on them to see how many times this error has occurred. I am wanting to find out when the first date the error occurred, which is fairly straight forward, but also the last date it occurred too to see how long this error has been persisting.
Below I show both my current output and expected output
Below I show my code. What changes would I need to make in order to display the last date as well as the first date? I have tried using LastOrDefault()
but this doesn't actually work as when the LINQ query is converted into a SQL statement, there is no BOTTOM 1
command.
public ActionResult Errors(string sortOrder, int? page)
{
ViewBag.CurrentSort = sortOrder;
ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";
var queryString = RouteData.Values["id"];
var applications = db.ElmahErrors.Where(s => s.Application.Replace("/", "").Replace(".", "") == queryString)
.GroupBy(s => s.Type)
.Select(grp => new ErrorCountModel
{
ErrorCount = grp.Count(),
ElmahError = grp.FirstOrDefault()
});
switch (sortOrder)
{
default:
applications = applications.OrderBy(s => s.ElmahError.TimeUtc);
break;
}
int pageSize = Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["DefaultPageSize"]);
int pageNumber = (page ?? 1);
return View(applications.ToPagedList(pageNumber, pageSize));
}
public class ErrorCountModel
{
public int ErrorCount { get; set; }
public ElmahError ElmahError { get; set; }
}
Any help on this matter would be greatly appreciated.
Thanks in advance.
Upvotes: 2
Views: 81
Reputation: 12132
Another way to do this would have been to create a view model as follows:
public class ElmahErrorViewModel {
public Guid ID {get;set;}
public string Application {get;set;}
public string Host {get;set;}
public string Type {get;set;}
public int ErrorCount {get;set;}
public DateTime Min {get;set;}
public DateTime Max {get;set;}
}
And then just:
var applications = db.ElmahErrors.Where(s => s.Application.Replace("/", "").Replace(".", "") == queryString)
.GroupBy(s => new { s.Type, s.ID, s.Application, s.Host })
.Select(grp => new ElmahErrorViewModel {
ID = grp.Key.ID,
Application = grp.Key.Application,
Host = grp.Key.Host,
Type = grp.Key.Type,
ErrorCount = grp.Count(),
Min = grp.Min(m => m.TimeUtc),
Max = grp.Max(m => m.TimeUtc),
});
The idea being that this returns a flattened model ready to go whereas I assume with a LastElmahError
property you still have to flatten it at some point to display it in the UI and the only field you actually want out of that is TimeUtc
so most of it is redundant.
Upvotes: 0
Reputation: 27357
Side note: The following is not guaranteed to give you the newest error, because you haven't told it to sort
ElmahError = grp.FirstOrDefault()
It should be this:
ElmahError = grp.OrderBy(s => s.ElmahError.TimeUtc).FirstOrDefault();
I would have expected .LastOrDefault() to work, but if it really doesn't, you can do this:
LastElmahError = grp.OrderByDescending(s => s.ElmahError.TimeUtc).FirstOrDefault();
Essentially, you reverse the ordering of the first error.
Also, add this to your ErrorCountModel
model class:
public ElmahError LastElmahError { get; set; }
Upvotes: 0