Как я могу linq объект группировки - PullRequest
0 голосов
/ 22 февраля 2019

Как я могу сгруппировать эти объекты?Я могу получить через LINQ и связать это.Но это бесполезно, потому что мне нужна обратная группировка.Например:

MainGroup> Список групп> Список подгрупп

Может быть, я смогу сделать это с помощью запроса LINQ, который сначала получит значения.Я не знаю.

Я начинающий пользователь LINQ.У меня нет много информации.Спасибо заранее за вашу помощь.Я получаю и связываю данные mongodb следующим образом:

var subGroupCollection = Database.GetCollection<SubGroup>(typeof(SubGroup).Name);
var groupCollection = Database.GetCollection<Group>(typeof(Group).Name);
var mainGroupCollection = Database.GetCollection<MainGroup>(typeof(MainGroup).Name);

var query = from sg in subGroupCollection.AsQueryable()
            join mg in mainGroupCollection on sg.MainGroupId equals mg.Id into mainGroups
            join z in groupCollection on sg.GroupId equals z.Id into groups
            select new SoccerOddType
            {
                Id = sg.Id,
                IsActive = sg.IsActive,
                GroupId = sg.GroupId,
                Name = sg.Name,
                LastUpdateDate = sg.LastUpdateDate,
                CreatedDate = sg.CreatedDate,
                Order = sg.Order,
                Discount = sg.Discount,
                DiscountType = sg.DiscountType,
                MainGroupId = sg.MainGroupId,
                MainGroup = mainGroups.First(),
                Group = groups.First()
            };

От:

public class MainGroup
{
    public string Id { get; set; }
    public string Name { get; set; }
    public bool IsActive { get; set; }
}

public class Group
{
    public string Id { get; set; }
    public string MainGroupId { get; set; }
    [BsonIgnore] public Group MainGroup { get; set; }
    public string Name { get; set; }
    public bool IsActive { get; set; }
}

public class SubGroup
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string MainGroupId { get; set; }
    public string GroupId { get; set; }
    [BsonIgnore] public Group MainGroup { get; set; }
    [BsonIgnore] public Group Group { get; set; }
    public bool IsActive { get; set; }
    public decimal Discount { get; set; }
    public EnmDiscountType DiscountType { get; set; }
}

До:

public class MainGroupViewModel
{
    public string Id { get; set; }
    public string Name { get; set; }
    public bool IsActive { get; set; }
    public List<GroupViewModel> Groups { get; set; }
}

public class GroupViewModel
{
    public string Id { get; set; }
    public string MainGroupId { get; set; }
    public string Name { get; set; }
    public bool IsActive { get; set; }
    public List<SubGroupViewModel> SubGroups { get; set; }
}

public class SubGroupViewModel
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string MainGroupId { get; set; }
    public string GroupId { get; set; }
    public bool IsActive { get; set; }
    public decimal Discount { get; set; }
    public EnmDiscountType DiscountType { get; set; }
}

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Я бы, наверное, пошел с .Select().

var subGroups = subGroupCollection.Select(sg => new SubGroupViewModel
{
    Id = sg.Id,
    Name = sg.Name,
    MainGroupId = sg.MainGroupId,
    GroupId = sg.GroupId,
    IsActive = sg.IsActive,
    Discount = sg.Discount,
    DiscountType = sg.DiscountType
});

var groups = groupCollection.Select(g => new GroupViewModel 
{
    Id = g.Id,
    MainGroupId = g.MainGroupId,
    Name = g.Name,
    IsActive = g.IsActive,
    SubGroups = subGroups.Where(sg => sg.GroupId == g.Id).ToList() 
});

var mainGroups = mainGroupCollection.Select(mg => new MainGroupViewModel
{
    Id = mg.Id,
    Name = mg.Name,
    IsActive = mg.IsActive,
    // .Any() or .All() here?
    Groups = groups.Where(g => g.SubGroups.Any(sg => sg.MainGroupId == mg.Id))
});
0 голосов
/ 28 февраля 2019

Если у вас есть отношение «один ко многим» с использованием внешнего ключа, и вам нужны элементы с их подэлементами, например, «Школы с их учениками», «Клиенты с их заказами», «Главные группы» с их подгруппами, тогда вы можете использоватьпросто выберите, чтобы получить свой результат, или используйте GroupJoin

Select

var result = mainGroupCollection.Select(mainGroup => new MainGroupViewModel
{
    Id = mainGroup.Id,
    Name = mainGroup.Name,
    ...

    // Keep only the Groups of this MainGroup, using foreign key
    Groups = groupCollection
        .Where(group => group.MainGroupId == mainGroup.Id)
        .Select(group => new GroupViewModel
        {
            Id = group.Id,
            Name = group.Name,
            ...

            // Keep only the subGroups of this Group, using foreign key
            SubGroups = subGroupCollection
                .Where(subGroup => subGroup.GroupId == group.Id)
                .Select(subGroup => new SubGroupViewModel
                {
                    Id = group.Id,
                    Name = group.Name,
                    ...
                })
                .ToList(),
        })
        .ToList(),
});

Хотя этот метод работает, он не очень эффективен, потому что для каждого элемента вmainGroupCollection он должен перечислять по всей GroupCollection, а для каждого элемента он должен перечислять по всей SubGroupCollection.

В зависимости от того, какую СУБД вы используете при запросе из базы данных, это не является большой проблемой.Тем не менее, я бы пошел для GroupJoin

GroupJoin

Enumerable.GroupJoin гораздо более эффективен (или эквивалент IQueryable).Версия Enumerable использует словарь, чтобы увидеть, нашел ли он элемент с таким идентификатором, поэтому ему не нужно перечислять более одного раза по каждой коллекции.

// GroupJoin the mainGroupCollection with the groupCollection:
var result = mainGroupCollection.GroupJoin(groupCollection,
    mainGroup = mainGroup.Id,         // from every mainGroup take the primary key
    group => group.MainGroupId,       // from every group take the foreign key

    // ResultSelector: for every mainGroup and its groups make one MainGroupViewModel
    (mainGroup, groupsOfThisMainGroup) => new MainGroupViewModel
    {
        Id = mainGroup.Id,
        Name = mainGroup.Name,
        ...

        // for the Groups: GroupJoin the groups of this main group with the subGroups
        Groups = groupsOfThisMainGroup.GroupJoin(subGroupCollection,
            groupOfThisMainGroup => groupOfThisMainGroup.Id,
            subGroup => subGroup.GroupId,

            // result selector
            (group, subGroupsOfThisGroup) => new GroupViewModel
            {
                Id = group.Id,
                Name = group.Name,

               SubGroups = subGroupsOfThisGroup.Select(subGroup => new SubGroupViewModel
               {
                    Id = subGroup.Id,
                    Name = subGroup.Name,
                    ...
               })
               .ToList(),
        })
        .ToList(),
    });
...