简体   繁体   中英

Linq List problems with GroupBy and Count

Given the data below, I am trying to write a LINQ statement that will group by ListOfAdmin by id so it will only display one user. I am also checking that the count is not 0 . The record one has no ListOfAdmin so that Count==0 should return null but it is displaying records for ListOfAdmin . Also once I add //.GroupBy(f => f.id) I get the error Cannot implicitly convert type 'System.Collections.Generic.List

All of the other section is working fine.

Once I add ListOfSubscription with no record for ListOfAdmin I get the error

LINQPad Example

        class Subscription
        {
            public int SubscriptionId { get; set; }
            public int ParentProductId { get; set; }
            public string ParentProductName { get; set; }
            public string ChildProductName { get; set; }
            public int ChildProductId { get; set; }
            public int GroupId { get; set; }
            public DateTime? EndDate { get; set; }
            public List<admin> ListOfAdmin { get; set; }
        }
        class SubscriptionViewModel
        {
            public int SubscriptionId { get; set; }
            public int ParentProductId { get; set; }
            public string ParentProductName { get; set; }
            public string SubscriptionIds { get; set; }
            public int GroupId { get; set; }
            public List<SubscriptionChildViewModel> ListOfSubscriptionChild { get; set; }
            public List<AdminViewModel> ListOfAdmin { get; set; }
        }
        class SubscriptionChildViewModel
        {
            public string ChildProductName { get; set; }
            public int ChildProductId { get; set; }
        }

        class AdminViewModel
        {
            public int id { get; set; }
            public string name { get; set; }
        }
        class admin
        {
            public int id { get; set; }
            public string name  { get; set; }
        }

void Main()
{
List<Subscription> ListOfSubscription = new List<Subscription>();


                List<admin> ListOfAdmin = new List<admin>();
                ListOfSubscription.Add(new Subscription() { SubscriptionId = 1, ParentProductId = 4, ChildProductId = 4, ParentProductName = "Product 1", ChildProductName = "Product 1", GroupId = 362,ListOfAdmin= ListOfAdmin });
                ListOfAdmin.Clear(); 
                ListOfAdmin.Add(new admin() { id = 1, name= "Mike"});
                ListOfAdmin.Add(new admin() { id = 2, name = "Bill" });             
                ListOfSubscription.Add(new Subscription() { SubscriptionId = 2, ParentProductId = 114, ChildProductId = 1, ParentProductName = "Product 2", ChildProductName = "Product 3", GroupId = 1,  ListOfAdmin= ListOfAdmin });
                ListOfSubscription.Add(new Subscription() { SubscriptionId = 3, ParentProductId = 114, ChildProductId = 2, ParentProductName = "Product 2", ChildProductName = "Product 4", GroupId = 1,  ListOfAdmin = ListOfAdmin });

                var groupedSubscriptions = ListOfSubscription.GroupBy(u => u.GroupId);

                var result = groupedSubscriptions.Select(grp1 => new
                {
                    GroupId = grp1.Key,
                    Subscriptions = grp1.GroupBy(subscr => new
                    {
                        subscr.ParentProductId,
                        subscr.ParentProductName,
                        //subscr.ListOfAdmin
                    })
                    .Select(grp2 => new SubscriptionViewModel
                    {
                        GroupId = grp1.Key,
                        ParentProductId = grp2.Key.ParentProductId,
                        ParentProductName = grp2.Key.ParentProductName,
                        SubscriptionIds = string.Join(",", grp2.Select(y => y.SubscriptionId)),
                        ListOfSubscriptionChild = grp2
                            .Where(subsc => subsc.ChildProductId != grp2.Key.ParentProductId)
                            .Select(subsc => new SubscriptionChildViewModel
                            {
                                ChildProductId = subsc.ChildProductId,
                                ChildProductName = subsc.ChildProductName
                            })
                            .ToList(),     
                            ListOfAdmin = (grp2.SelectMany(y => y.ListOfAdmin).Count()) == 0 ? null : grp2.SelectMany(y => y.ListOfAdmin)
                                 .Select(a => new AdminViewModel
                                 {
                                     id = a.id,
                                     name = a.name
                                 })
                                 //.GroupBy(f => f.id)
                                .ToList(),
                })
                });

                var x = result.SelectMany((s => s.Subscriptions));
        
                Console.Write(x);
}

Updated: using List<IGrouping<int, AdminViewModel>> I am getting dups. 在此处输入图片说明

According to the documentation , GrouBy() returns an object of type IEnumerable<IGrouping<TKey,TElement>> .

In your case,

(grp2.SelectMany(y => y.ListOfAdmin).Count()) == 0 ? null : grp2.SelectMany(y => y.ListOfAdmin)
    .Select(a => new AdminViewModel
         {
             id = a.id,
             name = a.name
         })
    .GroupBy(f => f.id)
    .ToList()

return an object of type List<IGrouping<int, AdminViewModel>>

In order for your code to work, you just need to change the type of the SubscriptionViewModel.ListOfAdmin attribute.

        class SubscriptionViewModel
        {
            [...]
            public List<IGrouping<int, AdminViewModel>> ListOfAdmin { get; set; }
        }

Let's take a look at the exact error: Cannot implicitly convert type 'System.Collections.Generic.List<System.Linq.IGrouping<int,Program.AdminViewModel>>' to 'System.Collections.Generic.List<Program.AdminViewModel>' .

It is pretty clear: you are trying to assign a value (of type List<IGrouping<int,Program.AdminViewModel>> ) that is not of the expected type ( List<Program.AdminViewModel> ).

You can remedy this by changing SubscriptionViewModel , so that ListOfAdmin will be List<IGrouping<int, AdminViewModel>> , as @itectori suggested.

However, I don't think that's what you're looking for. If I understand correctly, ListOfAdmin should contain, well, the admins. If that is the case, simply select the first item of every IGrouping , like this:

 ListOfAdmin = (grp2.SelectMany(y => y.ListOfAdmin).Count()) == 0 ? null : grp2.SelectMany(y => y.ListOfAdmin)
    .Select(a => new AdminViewModel
    {
       id = a.id,
       name = a.name
    })
.GroupBy(f => f.id)
.Select(g => g.First())
.ToList(),

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