1

Need help in creating LINQ query to group and filter with related entities.

Here is my model classes.

public class Application
    {
        [DisplayName("Application")]
        public int ApplicationId { get; set; }
        [DisplayName("Application")]
        public string Name { get; set; }
        public List<DashboardEntry> DashboardEntries { get; set; }
    }

public class Cluster
    {
        [DisplayName("Cluster")]
        public int ClusterId { get; set; }
        [DisplayName("Cluster")]
        public string Name { get; set; }
    }

[Bind(Exclude = "AlbumId")]
    public class DashboardEntry
    {
        [ScaffoldColumn(false)]
        public int DashboardEntryId { get; set; }        
        public int ClusterId { get; set; }        
        public int ApplicationId { get; set; }        
        public HealthStatusIndicator Status { get; set; }
        public string Incident { get; set; }
        public string Remarks { get; set; }

        public virtual Cluster Cluster { get; set; }
        public virtual Application  Application { get; set; }
    }

Index action method is as follows

public ActionResult Index()
        {
            //var dashboardEntries = db.DashboardEntries.Include(d => d.Application).Include(d => d.Cluster);

            var dashboardEntries = db.DashboardEntries
                                   .Include(d => d.Application)
                                   .Include(d => d.Cluster)                                   
                                   .GroupBy(d => d.Application);

            return View(dashboardEntries.ToList());
        }

In the view, model declaration is as below.

@model IEnumerable<HealthCheckIndex.Models.DashboardEntry>

I'm getting an error

The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery1[System.Linq.IGrouping2[HealthCheckIndex.Models.Application,HealthCheckIndex.Models.DashboardEntry]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[HealthCheckIndex.Models.DashboardEntry]'.

If I change the model declaration in view as below, I'm getting a another error that Cluster is not accessible.

@model IEnumerable>

I want to group the dashboard entries into different applications and filter the groups by choosing the max dashboard entry from each group.

kunaguvarun
  • 703
  • 1
  • 10
  • 29
  • 4
    It's best not to pass EF Models directly to your View. Create a ViewModel that contains the data without navigation properties that the controller creates and passes to your View – Tah Mar 27 '16 at 07:50
  • Thanks for the advice. I will ultimately change to this approach but right now my target is to get the app up and running. I'm going to opt the SelectMany(c=>c) for now – kunaguvarun Mar 27 '16 at 12:24

1 Answers1

2

The type that you are passing currently to the view does not match the specified type

@model IEnumerable<HealthCheckIndex.Models.DashboardEntry>

Currently you are passing something like a dictionary where the key is Application and the value is a IEnumerable of HealthCheckIndex.Models.DashboardEntry

In order to make it you have one of 2 options:

  1. Replace the last line of the controller action with

    return View(dashboardEntries.SelectMany(c=> c).ToList());

  2. Change model definition in the view to match the list your returning

Vojtěch Dohnal
  • 7,867
  • 3
  • 43
  • 105
Ali Hajahmed
  • 184
  • 3
  • Thanks for SelectMany(c=>c). It returns all the records grouped into Applications. How do I filter the groups based on max of dashboardEntryId from each group? – kunaguvarun Mar 27 '16 at 12:25
  • Instead of SelectMany just use the following "Select(c=> c.Max(x=> x.DashboardEntryId))" – Ali Hajahmed Mar 27 '16 at 13:48
  • Thank you. I came across this http://stackoverflow.com/questions/470440/how-to-select-only-the-records-with-the-highest-date-in-linq which also seems to solve the problem – kunaguvarun Mar 27 '16 at 13:52