user3046164
user3046164

Reputation: 159

Linq expression with GroupBy

I have a linq expression that I want to group and and cast as hard type List<DocumentGroup>

This linq query works correctly:

var DocumentGroups = (from dt in DocumentTypes
                       let dg = dt.DocumentGroup
                       select new DocumentGroup(){
                           Name = dg.Namn, 
                           Id = dg.Id
                        }).GroupBy(group => group.Id).ToList(); 

Now I want do the same query and cast it to a List<DocumentGroup> but I receive this error:

Unable to cast object of type 'Grouping[System.Guid,ConsoleApplication1+DocumentGroup]' to type 'DocumentGroup'.

List<DocumentGroup> DocumentGroups = (from dt in DocumentTypes
                           let dg = dt.DocumentGroup
                           select new DocumentGroup(){
                               Name = dg.Namn,
                               Id = dg.Id
                           }).GroupBy(group => group.Id).Cast<DocumentGroup>.ToList(); 

If I remove .GroupBy(group => group.Id) from the linq expression, it works correctly, but I need the group expression to filter it out. How can I make this work?

The DocumentGroup class

public class DocumentGroup
{
    public string Name { get; set; }
    public Guid Id { get; set; }
}

Upvotes: 1

Views: 1435

Answers (2)

bwin
bwin

Reputation: 1

Before doing the GroupBy you have a list of DocumentGroup (like single dimensional array)

1    Name1       <record 1 of DocumentGroup>
1    Name2       <record 2 of DocumentGroup>
1    Name3       <record 3 of DocumentGroup>
2    Name4       <record 4 of DocumentGroup>
3    Name5       <record 5 of DocumentGroup>

After doing the GroupBy you have a list of IGrouping<int, DocumentGroup> (like a two dimensional array)

1    1    Name1       --|
     1    Name2         -- <record 1 of IGrouping<int, DocumentGroup>
     1    Name3       --|
2    2    Name4            <record 2 of IGrouping<int, DocumentGroup>>
3    3    Name5            <record 3 of IGrouping<int, DocumentGroup>>

So to get the DocumentGroup you need to access from the Grouping item first, then you get the DocumentGroup, example:

var groupOfDocumentGroups = /* omitted code */
     select new DocumentGroup() { Name = dg.Namn, Id = dg.Id })
     .GroupBy(group => group.Id)
     .ToList();

foreach(var groupItem in groupOfDocumentGroups)
{
    // groupItem type is IGrouping<int, DocumentGroup>
    // groupItem has `Key` property which is an integer of the Id.
    // groupItem is also a collection that you can do enumeration.
    foreach(var item in groupItem)
    {
        // there you go, item type is DocumentGroup
    }
}

but I must have the group expression to filter it out

I assume you want to get all unique DocumentGroups in all DocumentTypes, then Salman22 answer is what you're looking for.

You can also use Distinct in this case. If you're working with linq to entities, you can just have.

var documentGroups = context.DocumentTypes
    .Select(x => x.DocumentGroup)
    .Distinct()
    .ToList();

If you're working with linq to object, you can implement IEqualityComparer<DocumentGroup> first.

class DocumentGroupComparer : IEqualityComparer<DocumentGroup>
{
    public bool Equals(DocumentGroupx, DocumentGroupy)
    {
        return x.Id == y.Id;
    }
    public int GetHashCode(DocumentGroup obj)
    {
        return obj.Id.GetHashCode();
    }
}

var documentGroups = DocumentTypes
    .Select(x => x.DocumentGroup)
    .Distinct(new DocumentGroupComparer())
    .ToList();

Upvotes: 0

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101681

When you use GroupBy you get groups. So casting a group to a single item will fail.

If all you want to do is remove duplicates then you can select the first item from each group:

var DocumentGroups = (from dt in DocumentTypes
                      let dg = dt.DocumentGroup
                      select new DocumentGroup() 
                             { 
                                Name = dg.Namn, 
                                Id = dg.Id 
                             }).GroupBy(group => group.Id)
                               .Select(g => g.First())
                               .ToList();

Upvotes: 4

Related Questions