简体   繁体   English

Linq多组加入C#

[英]Linq multiple group join in c#

I need to create a structure like below. 我需要创建如下结构。

  • section1 第1节
    • question1 问题1
    • message1 message1
  • section2 第2节
    • quesiton2 quesiton2
    • message1 message1
    • message2 message2

I wrote the below code to generate this. 我编写了以下代码以生成此代码。

using System;
using System.Linq;
using System.Collections.Generic;


public class Program
{
    public static void Main()
    {
        // Question collection
        IList<Question> QuestionList = new List<Question>() { 
                new Question() { QuestionID = 1, QuestionName = "q1", SectionID = 1 } ,
                new Question() { QuestionID = 2, QuestionName = "q2",   SectionID = 1 } ,
                new Question() { QuestionID = 3, QuestionName = "q3",  SectionID = 2 } ,
                new Question() { QuestionID = 4, QuestionName = "q4" ,  SectionID = 2 } ,
                new Question() { QuestionID = 5, QuestionName = "q5"  } 
            };

        IList<Section> SectionList = new List<Section>() { 
                new Section(){ SectionID = 1, SectionName="Section 1"},
                new Section(){ SectionID = 2, SectionName="Section 2"},
                new Section(){ SectionID = 3, SectionName="Section 3"}
            };
        IList<Messages> MessagesList = new List<Messages>() { 
                new Messages(){ MessagesID = 1, MessagesName="Message 1",QuestionID=1},
                new Messages(){ MessagesID = 2, MessagesName="Message 2",QuestionID=1},
                new Messages(){ MessagesID = 3, MessagesName="Message 3",QuestionID=2}
            };
        var groupJoin = SectionList.GroupJoin(QuestionList,  //inner sequence
                                sct => sct.SectionID, //outerKeySelector 
                                s => s.SectionID,     //innerKeySelector

                                (sct, QuestionsGroup) => new // resultSelector 
                                {
                                    Questions = QuestionsGroup,

                                    SectionName = sct.SectionName
                                });

            var groupJoisn = QuestionList.GroupJoin(MessagesList,  //inner sequence
                                sct => sct.QuestionID, //outerKeySelector 
                                s =>s.QuestionID,     //innerKeySelector
                                (sct, QuestionsGroup) => new // resultSelector 
                                {
                                    Questions = QuestionsGroup,
                                    SectionName = sct.QuestionName
                                });



        foreach (var item in groupJoisn)
        { 
            Console.WriteLine(item.SectionName );

            foreach(var stud in item.Questions)
                Console.WriteLine(stud.MessagesName);
        }
        Console.WriteLine("-----------------");
        foreach (var item in groupJoin)
        { 
            Console.WriteLine(item.SectionName );

            foreach(var stud in item.Questions)
                Console.WriteLine(stud.QuestionName);
        }
    }

}

public class Question{

    public int QuestionID { get; set; }
    public string QuestionName { get; set; }
    public int SectionID { get; set; }
}
public class Messages{

    public int MessagesID { get; set; }
    public string MessagesName { get; set; }
    public int QuestionID { get; set; }
}
public class Section{

    public int SectionID { get; set; }
    public string SectionName { get; set; }
}

Unfortunately, i couldnt find a way to join the two group. 不幸的是,我找不到加入这两个小组的方法。 because the section and questions connected using sectionid whereas questions and messages connected using questionid. 因为部分和问题使用sectionid连接,而问题和消息则使用Questionid连接。 When I using second group join im getting error questionid not exists in this context. 当我使用第二组联接时,在这种情况下不存在错误questionid。 how can i resolve this. 我该如何解决。

your creation structure should be changed but if you want a solution that keeps most of your creation structure you could use this 您的创建结构应该更改,但是如果您想要一个可以保留大部分创建结构的解决方案,则可以使用此方法

Note however using where in each question and each section is not good for performance. 但是请注意,在每个问题和每个部分中使用where不利于性能。 you should rather create the message list and the question list inside the creation of the section list. 您应该在部分列表的创建中创建消息列表和问题列表。

IList<Messages> MessagesList = new List<Messages>() {
  new Messages(){ MessagesID = 1, MessagesName="Message 1",QuestionID=1},
  new Messages(){ MessagesID = 2, MessagesName="Message 2",QuestionID=1},
  new Messages(){ MessagesID = 3, MessagesName="Message 3",QuestionID=2}
};

// Question collection
IList<Question> QuestionList = new List<Question>() {
  new Question() { QuestionID = 1, QuestionName = "q1", SectionID = 1,messages = MessagesList.Where(message=> message.QuestionID==1).ToList() } ,
  new Question() { QuestionID = 2, QuestionName = "q2",   SectionID = 1,messages = MessagesList.Where(message=> message.QuestionID==2).ToList() } ,
  new Question() { QuestionID = 3, QuestionName = "q3",  SectionID = 2,messages = MessagesList.Where(message=> message.QuestionID==3).ToList() } ,
  new Question() { QuestionID = 4, QuestionName = "q4" ,  SectionID = 2 ,messages = MessagesList.Where(message=> message.QuestionID==4).ToList()} ,
  new Question() { QuestionID = 5, QuestionName = "q5" ,  SectionID = 2 ,messages = MessagesList.Where(message=> message.QuestionID==5).ToList() }
};  

IList<Section> SectionList = new List<Section>() {
  new Section(){ SectionID = 1, SectionName="Section 1",questions = QuestionList.Where(question=> question.SectionID == 1).ToList()},
  new Section(){ SectionID = 2, SectionName="Section 2",questions = QuestionList.Where(question=> question.SectionID == 2).ToList()},
  new Section(){ SectionID = 3, SectionName="Section 3",questions = QuestionList.Where(question=> question.SectionID == 3).ToList()}
};

foreach (var section in SectionList)
{
  Console.WriteLine("Section: " + section.SectionName);
  foreach (var question in section.questions)
  {
     Console.WriteLine("\tQuestion: " + question.QuestionName);
     foreach (var message in question.messages)
     {
        Console.WriteLine("\t\tMessage: " + message.MessagesName);
     }
  }
}

you will have to change your classes slightly for this. 为此,您将不得不稍微更改课程。

public class Question
{

    public int QuestionID { get; set; }
    public string QuestionName { get; set; }
    public int SectionID { get; set; }

    public List<Messages> messages { get; set; }
}
public class Messages
{

    public int MessagesID { get; set; }
    public string MessagesName { get; set; }
    public int QuestionID { get; set; }
}
public class Section
{

    public int SectionID { get; set; }
    public string SectionName { get; set; }

    public List<Question> questions { get; set; }
}

Your request doesn't match with your objects, do you want in all sections a unique list combine Message and Question ? 您的请求与您的对象不匹配,是否要在所有部分中都将消息和问题组合在一起的唯一列表?

Or if you want to have a tree like Section => Questions => Messages you can do it like this : 或者,如果您想要像Section => Questions => Messages这样的树,可以这样:

var group1 = SectionList.Select(section => new Section
{
    SectionID = section.SectionID,
    SectionName = section.SectionName,
    Questions = QuestionList.Where(question => question.SectionID.Equals(section.SectionID))
        .Select(question => new Question
        {
            QuestionID = question.QuestionID,
            QuestionName = question.QuestionName,
            SectionID = section.SectionID,
            Messages = MessagesList.Where(message => message.QuestionID.Equals(question.QuestionID))
                .Select(message => new Messages
                {
                    MessagesID = message.MessagesID,
                    MessagesName = message.MessagesName,
                    QuestionID = message.QuestionID
                })
        })
});

Of course you need to change a little bit your class : 当然,您需要对课程进行一些更改:

public class Question
{

    public int QuestionID { get; set; }
    public string QuestionName { get; set; }
    public int SectionID { get; set; }
    public IEnumerable<Messages> Messages { get; set; }
}

public class Section
{

    public int SectionID { get; set; }
    public string SectionName { get; set; }
    public IEnumerable<Question> Questions { get; set; }
}

You can join QuestionList with MessagesList into QuestionMessagesList . 您可以将QuestionListMessagesList加入QuestionMessagesList After that, you need to join QuestionMessagesList with SectionList . 之后,您需要将QuestionMessagesListSectionList结合SectionList

var questionMessages = QuestionList.GroupJoin(MessagesList,
                q => q.QuestionID,
                m => m.QuestionID,

                (Question, Messages) => new { Question, Messages }
            );

var groupJoin = SectionList.GroupJoin(questionMessages,
                sct => sct.SectionID,
                s => s.Question.SectionID,

                (sct, QuestionsGroup) => new
                {
                    Questions = QuestionsGroup,
                    SectionName = sct.SectionName
                });

Then: 然后:

            foreach (var item in groupJoin)
            {
                Console.WriteLine(item.SectionName);

                foreach (var stud in item.Questions)
                {
                    Console.WriteLine($" - {stud.Question.QuestionName}");

                    foreach (var message in stud.Messages)
                    {
                        Console.WriteLine($"  -- {message.MessagesName}");
                    }
                }
            }

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM