TanvirArjel TanvirArjel - 17 days ago 6
C# Question

Group By Multiple Column In LINQ in C#

Attention : I have seen there are lots of questions like this in stack overflow. But is not working for me as i have slight difference. So Please don't mark it as duplicate until reading the whole question properly and understanding the scenario I want.

I have class like as follows:

public class ActualClass
{
public string BookName { get; set; }
public string IssuerName { get; set; }
public DateTime DateOfIssue { get; set; }
public bool Status { get; set; }
}


It has following data in the table:
enter image description here

I would like to group them by IssuerName and DateOfIssue for the following viewModel class:

public class ViewModel
{
public string IssuerName { get; set; }
public DateTime DateOfIssue { get; set; }
public List<string> Books { get; set; }
}


And Data will displayed as follows:(Screenshot data will be replaced by the preivous table data after successful grouping)
enter image description here

Special attention: Is there any wrong in my ViewModel accroding to my expectation.

Tried a lot after following some stackoverflow anwser but did not work for me. Any help will be highly appreciated.

The Code I have tried:

var viewmodel = from b in db.BookIssues
group b by new
{
b.IssuerName,
b.DateOfIssue
}
into g
select new ViewModel()
{
Name = g.key.IssuerName,
DateOfIssue = g.Key.DateOfIssue,
Books = g.ToList() //Actually this line of is not working
};

Answer

Books = g.ToList() //Actually this line of is not working

Probably because Books property is type of List<string>, not List<ActualClass>.

Can you please try this query, I added b.Select(bn => bn.BookName).ToList() to extract only names of books:

var books = new List<ActualClass>
{
   new ActualClass { BookName = "A", DateOfIssue = new DateTime(2015, 10, 10, 10, 10, 0), IssuerName = "1" },
   new ActualClass { BookName = "B", DateOfIssue = new DateTime(2015, 10, 10, 10, 10, 0), IssuerName = "1" },
   new ActualClass { BookName = "C", DateOfIssue = new DateTime(2015, 10, 10, 10, 10, 0), IssuerName = "1" },
   new ActualClass { BookName = "D", DateOfIssue = new DateTime(2015, 10, 10, 10, 10, 0), IssuerName = "2" },
   new ActualClass { BookName = "E", DateOfIssue = new DateTime(2015, 10, 10, 12, 10, 0), IssuerName = "2" },
   new ActualClass { BookName = "F", DateOfIssue = new DateTime(2015, 10, 10, 12, 10, 0), IssuerName = "2" }
};

var result = books.GroupBy(x => new { x.IssuerName, x.DateOfIssue })
                .Select(b => new ViewModel
                {
                    Books = b.Select(bn => bn.BookName).ToList(),
                    DateOfIssue = b.Key.DateOfIssue,
                    IssuerName = b.Key.IssuerName
                });

I grouped by: x.IssuerName, x.DateOfIssue

Than you can read IssuerName and DateOfIssue from KEY in SELECT statement.

Key reffer to values added in new { x.IssuerName, x.DateOfIssue } statement.