문제

I have Question and Answer tables in a database. I used Join to select questions with answers and tried to get questions and answers with LINQ. Here is my code:

List<Question> newQuestionList = 
    (from q in dt.AsEnumerable()
     where (q.Field<Guid>("Question") != null))
     select new Question
     {
         Oid = q.Field<Guid>("Question"),
         QuestionContext = q.Field<String>("QuestionContext"),
         Priority = q.Field<Int32>("Priority"),
         Order = q.Field<Int32>("OrderQuestion"),
         Subject = q.Field<Guid>("Subject"),
         Answers = (from a in dt.AsEnumerable()
                    where a.Field<Guid>("Question") == q.Field<Guid>("Question")
                    select
                    new Answer
                    {
                        Oid = a.Field<Guid>("AnswerOid"),
                        AnswerContext = a.Field<String>("Answer"),
                        IsCorrect = a.Field<bool>("Correct")
                    }).ToList()
         }).Distinct().ToList();

There are a lot of rows that have the same question (Id). It iterates through all. I need to iterate only once for a question. If I have 7 questions, and every question has 4 answers, this code gives me a list that's count is 28. Its count must be 7. Can anyone help?

public class Question
{
    private Guid oid;

    public Guid Oid
    {
        get { return oid; }
        set { oid = value; }
    }

    private string questionContext;

    public string QuestionContext
    {
        get { return questionContext; }
        set { questionContext = value; }
    }

    private int priority;

    public int Priority
    {
        get { return priority; }
        set { priority = value; }
    }

    private Guid subject;

    public Guid Subject
    {
        get { return subject; }
        set { subject = value; }
    }

    private List<Answer> answers;

    public List<Answer> Answers
    {
        get { return answers; }
        set { answers = value; }
    }

    private int order;

    public int Order
    {
        get { return order; }
        set { order = value; }
    }
}

public class Answer 
{
    private Guid oid;

    public Guid Oid
    {
        get { return oid; }
        set { oid = value; }
    }

    private string answerContext;

    public string AnswerContext
    {
        get { return answerContext; }
        set { answerContext = value; }
    }

    private bool isCorrect;

    public bool IsCorrect
    {
        get { return isCorrect; }
        set { isCorrect = value; }
    }      
}
도움이 되었습니까?

해결책

I believe you just want to group your questions using .GroupBy(n=>n.Oid) (I've made the assumption that each question has a unique Oid as it is a Guid)

var questions = (from q in dt.AsEnumerable()
                 where (q.Field<Guid>("Question") != null))
                 select new Question
                 {
                     Oid = q.Field<Guid>("Question"),
                     QuestionContext = q.Field<String>("QuestionContext"),
                     Priority = q.Field<Int32>("Priority"),
                     Order = q.Field<Int32>("OrderQuestion"),
                     Subject = q.Field<Guid>("Subject"),
                     Answers = (from a in dt.AsEnumerable()
                                where a.Field<Guid>("Question") == q.Field<Guid>("Question")
                                select new Answer
                                {
                                    Oid = a.Field<Guid>("AnswerOid"),
                                    AnswerContext = a.Field<String>("Answer"),
                                    IsCorrect = a.Field<bool>("Correct")
                                }).ToList()
                 }).GroupBy(n=>n.Oid).ToList();

This will not return a flat collection. If I understand your structure correctly, this will return 7 Unique questions which have been joined to their answers. You can choose to flatten this collection by getting the first answer if you don't care about the others. You would append this to your GroupBy(n=>n.Oid) for:

GroupBy(n=>n.Oid).Select(g => g.First()).ToList();

다른 팁

I think if you do grouping first, then you will not have to enumerate whole table for each question

List<Question> questions = 
    (from q in dt.AsEnumerable()
     where (q.Field<Guid>("Question") != null)
     group q by new {  Oid = q.Field<Guid>("Question"),
                       QuestionContext = q.Field<String>("QuestionContext"),
                       Priority = q.Field<Int32>("Priority"),
                       Order = q.Field<Int32>("OrderQuestion"),
                       Subject = q.Field<Guid>("Subject")
    } into g
    select new Question {
        Oid = g.Key.Oid,
        QuestionContext = g.Key.QuestionContext,
        Priority = g.Key.Priority,
        Order = g.Key.Order,
        Subject = g.Key.Subject,
        Answers = g.Select(a => new Answer() 
        {
            Oid = a.Field<Guid>("AnswerOid"),
            AnswerContext = a.Field<String>("Answer"),
            IsCorrect = a.Field<bool>("Correct")
        }).ToList()
    }).ToList();  
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top