【问题标题】:How do I do a table join using LINQ and entity framework 6?如何使用 LINQ 和实体框架 6 进行表连接?
【发布时间】:2014-10-15 00:39:25
【问题描述】:

我有三个表格:Exam > Objectives > 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,我不知道从哪里开始。

【问题讨论】:

  • 你当前的结构看起来不错,如果你从 db.Exam 开始,你会继续。
  • @KrunalPatil - 但是如果我从 db.Exam 开始,那么我该如何加入其他对象?

标签: c# sql asp.net linq entity-framework


【解决方案1】:

这是我在加入两个或多个表时通常会做的事情,不知道这是不是你要找的:

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;

【讨论】:

  • 是的!这是规则的 LINQ!
【解决方案2】:

假设 Entity Framework 已正确连接您的实体之间的关系,以下应返回单个考试以及相关的目标和详细信息:-

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

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

上述查询将在幕后使用 外部 联接,因此即使没有关联的目标/详细信息,也将始终返回考试(如果找到)。考试作为单个对象返回,如果适用,则包含子目标。

或者,以下将使用 inner 连接返回一个扁平的结果集:-

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 知道实体之间的关系,则通常没有必要。

【讨论】:

    【解决方案3】:

    这将返回分组选择的枚举,键加计数。最后转换为列表,以便可以检索当时的所有数据

     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”我们创建了一个新类型的对象,只有两个属性

    【讨论】:

      【解决方案4】:
      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
      

      【讨论】:

      • 不确定你的属性的正确名称,但它应该接近那个,希望你明白了。
      • joins 上的条件应使用equals 而不是=。应该是join o in objective on e.objectiveid equals o.id,其他连接也是一样。
      猜你喜欢
      • 1970-01-01
      • 2017-09-08
      • 1970-01-01
      • 2021-08-26
      • 1970-01-01
      • 2019-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多