实体框架:在多个“一对多”关系中过滤数据的最佳实践

时间:2016-01-27 11:26:53

标签: c# entity-framework linq

在这种情况下:

public class Software
{
    [Key]
    public int Id { get; set; }

    // Some properties

    public virtual ICollection<Release> Releases { get; set; }
}

public class Release
{
    [Key]
    public int Id {get; set;}

    public int Version {get; set;}

    public virtual Software Software {get; set;}
    public virtual ICollection<Report> Reports{get; set;}
}

public class Report
{ 
    [Key]
    public int Id {get; set;}

    // Some properties

    public virtual Release Release {get; set;}
}

如果我必须通过Software.Id和Release.version过滤报告,最好使用此查询:

from report in context.Reports
where report.Release.Version == filterVersion && 
      report.Release.Software.Id == filterId
select report

或者使用此查询?

from software in context.Softwares
where software.Id == filterId
     from release in software.Releases
     where release.Version == filterVersion
          from report in release.Reports
          select report

最好“先过滤”数据还是使用实体框架导航属性?

1 个答案:

答案 0 :(得分:1)

当然,对我们来说,无法确定哪个查询效果最佳。这主要取决于每个表中的索引和记录数,这两个记录都对执行计划产生了巨大影响。

但我认为在您的情况下,查询形状对于两种替代方案都是相同的。例如,report.Release.Versionrelease.Reports都会生成内部联接。并且谓词将以相同的方式生成。

因此,归结为个人喜好。

我总是倾向于将我的查询粗略地构建为......

  • from我想要的实体
  • where过滤器
  • select

...因为以后很容易添加/删除谓词。

那就是:

from report in context.Reports
where report.Release.Version == filterVersion && 
      report.Release.Software.Id == filterId
select report

另类......

from software in context.Softwares
where software.Id == filterId
     from release in software.Releases
     where release.Version == filterVersion
          from report in release.Reports
          select report

......谓词“到处都是”(好吧,它并不复杂,但你知道我的意思)。

但如果您想要包含来自所有实体的数据的投影,则图片会发生变化:

from report in context.Reports
where report.Release.Version == filterVersion && 
      report.Release.Software.Id == filterId
select new
{
    report.Name,
    report.Release.Version,
    report.Release.Software.Id,
    report.Release. ...
}

...因为所有点缀的引用都比......的可读性稍差。

from software in context.Softwares
where software.Id == filterId
     from release in software.Releases
     where release.Version == filterVersion
          from report in release.Reports
select new
{
    report.Name,
    release.Version,
    software.Id,
    release. ...
}

但同样,SQL查询可能仍然相同。