Как мне сделать объединение таблиц, используя LINQ и Entity Framework 6?

1

У меня три таблицы: Экзамен> Цели> ObjectiveDetails

Вот как они выглядят:

public class Exam
{
    public Exam()
    {
        this.Objectives = new HashSet<Objective>();
    }
    public int ExamId { get; set; }
    public int SubjectId { get; set; }
    public virtual ICollection<Objective> Objectives { get; set; }
}

public class Objective : AuditableTable
{
    public Objective()
    {
        this.ObjectiveDetails = new HashSet<ObjectiveDetail>();
    }
    public int ObjectiveId { get; set; }
    public int ExamId { get; set; }
    public int Number { get; set; }
    public virtual Exam Exam { get; set; }
    public virtual ICollection<ObjectiveDetail> ObjectiveDetails { get; set; }

}

public partial class ObjectiveDetail
{
    public int ObjectiveDetailId { get; set; }
    public int ObjectiveId { get; set; }
    public int Number { get; set; }
    public string Text { get; set; }
    public virtual Objective Objective { get; set; }
}

Должен ли я начать с экзамена следующим образом:

 var result = await db.Exams
                      .Where(e => e.Name == name)

или из ObjectiveDetails:

 var result = db.ObjectiveDetails .. ??

Как я могу получить объект, который показывает цели и объективные данные для данного экзамена? Должен ли я начинать с db.Exams или мне нужно начинать с db.ObjectiveDetails? Все, что мне нужно, это сделать соединение (если только в реляционном мире). Но с LINQ я не уверен, с чего начать.

  • 1
    Ваша текущая структура кажется хорошей, и если вы начнете с db.Exam - это правильный путь для продолжения.
  • 0
    @KrunalPatil - Но если я начну с db.Exam, то как мне присоединиться к другим объектам?
Теги:
linq
entity-framework

4 ответа

4
Лучший ответ

Это то, что я обычно делаю, когда речь идет о присоединении к двум или более таблицам, не знаю, что именно вы ищете:

var info = from p in db.Exam 
           join q in db.objective on p.objectiveid equals q.id
           join r in db.objectivedetails on q.objectivedeailsId equals r.id
           select new
                       {
                           ExamId  = p.ExamId 
                           SubjectId= p.SubjectId
                           ObjectiveId= q.ObjectiveId
                           Number = q.Number
                           ObjectiveDetailId = r.ObjectiveDetailId
                           Text = r.Text
                       } into x
           select x;
1

Предполагая, что Entity Framework правильно связала отношения между вашими объектами, следующее должно вернуть один экзамен вместе с связанными целями и деталями: -

var query = db.Exams.Include(e => e.Objectives.Select(o => o.ObjectiveDetails));

var examEntity = query.SingleOrDefault(e => e.ExamId == targetExamId);

Вышеприведенный запрос будет использовать внешние соединения за кулисами, поэтому Экзамен всегда будет возвращен (если найден), даже если нет связанных Целей/Подробности. Экзамен возвращается как единый объект с дочерними Целями, включенными, если применимо.

В качестве альтернативы, следующий результат возвращает сплющенный результирующий набор, используя внутренние соединения: -

var query = from exam in db.Exams
            from objective in exam.Objectives
            from detail in objective.ObjectiveDetails
            select new
            {
                ExamId = exam.ExamId,
                SubjectId = exam.SubjectId
                ObjectiveId = objective.ObjectiveId
                ObjectiveNumber = objective.Number
                DetailId = detail.DetailId
                DetailNumber = detail.Number
                Text = detail.Text
            };

var examDetails = query.Where(e => e.ExamId == targetExamId).ToArray();

Нет ничего плохого в использовании ключевого слова Linq "join" явно, но обычно это не нужно, если EF знает, как связаны сущности.

0

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

 var results = simulacao.Geracao
                .SelectMany(g => g.ObterCarteiras())
                .SelectMany(cg => cg.CarteiraGeneticaInvestimento)
                .SelectMany(cgi => cgi.HistoricoNaoPodeInvestir)
                .GroupBy(hnpi => hnpi.TipoNaoPodeInvestir)
                .Select(g => new { Tag = g.Key, Frequency = g.Count() })
                .ToList();

это имеет такое же поведение предыдущего, но два способа получить одну и ту же информацию с LINQ

var geracoes = (from g in simulacao.Geracao
                        from cg in g.ObterCarteiras()
                        from cgi in cg.CarteiraGeneticaInvestimento
                        from hnpi in cgi.HistoricoNaoPodeInvestir
                        group hnpi by hnpi.TipoNaoPodeInvestir into g
                        select new
                        {
                            TipoNaoPodeInvestir = Utilities.GetEnumDescription((EnumTipoNaoPodeInvestir)g.Key),
                            Count = g.Count()
                        }).ToList();

в конце мы можем преобразовать список в json-результат

return Json(geracoes, JsonRequestBehavior.AllowGet);

обратите внимание, что с помощью "select new" мы создаем новый тип объекта с двумя свойствами

-1
From e in db.Exam 
join o in objective on e.objectiveid = o.id
join od in objectivedetails on o.objectivedeailsId = od.id
select e
  • 0
    Не уверен в правильности названий ваших свойств, но это должно быть что-то близкое к этому, надеюсь, у вас есть идея.
  • 0
    Условия в обоих join должны использовать equals вместо = . Это должно быть join o in objective on e.objectiveid equals o.id , то же самое для другого соединения.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню