【问题标题】:OrderBy inside EF linqEF linq 中的 OrderBy
【发布时间】:2018-03-30 16:29:26
【问题描述】:

我有表 Sites 和相关表 PhotosPhotosSiteId 上获得了 FK。 照片的字段值可以是 PhotoNumber 等于 1、2 或 3。 我需要知道Site 是否有PhotosPhotoNumber = 1、2 和3。 我尝试了类似的方法,但我不知道如何通过DateDate 是 linq 内部的Photos 中的索引字段)订购照片,以便在有序列表中使用Any(),并订购一次,以优化这一点.我很困惑是否应该订购它?

  var sites = (from site in context.Sites
               select new
               {
                   Site = site,
                   Cam1 = context.Photos.Any(p => p.SiteId == site.SiteID && p.PhotoNumber == 1),
                   Cam2 = context.Photos.Any(p => p.SiteId == site.SiteID && p.PhotoNumber == 2),
                   Cam3 = context.Photos.Any(p => p.SiteId == site.SiteID && p.PhotoNumber == 3)
               }).ToList();

我知道最简单的方法可能是这样的:

var sitesToCameraIds = (from photo in context.Photos 
    select new { SiteId = photo.SiteId, CameraId = photo.PhotoNumber})
    .Distinct()
    .ToList().OrderBy(p => p.SiteId);

但这会非常慢,因为它需要检查所有照片以区分未索引字段PhotoNumber(不能作为索引,因为它只能是1-3),而不是我想使用Any()只要它在第一次匹配时停止搜索。

照片桌:

站点表:

【问题讨论】:

  • 您的问题令人困惑。您想知道一个站点是否为 1,2 和 3 的照片?听起来你是这样做的,然后你的问题是关于在没有代码示例的日期进行排序,也没有任何理由知道我可以告诉的日期。
  • @Erik Philips 我添加了表格图片。例如,我想知道 SiteId = 10 的站点是否只有 PhotoNumber = 1 的照片,或者它有任何 PhotoNumber = 1 和 PhotoNumber = 2 的照片
  • 日期与任何事情有什么关系?
  • 其他部分使用的日期,我认为按日期排序会提高 Any() 性能。可能我错了。
  • 听起来像是 XY 问题。 Any 将使用应该被索引的SiteID FK 列。问题是3个Any会生成3个EXISTS子查询。

标签: c# sql-server entity-framework linq entity-framework-6


【解决方案1】:

我需要知道网站是否有 PhotoNumber = 1、2 和 3

var photoNumbers = new List<int> {1,2,3}

var isSiteHasAnyPhotos = context
  .Photos
  .Any(p => p.SiteId = siteId && photoNumbers.Contains(q.PhotoNumber))

【讨论】:

    【解决方案2】:

    如果您没有从 SitesPhotos 的 EF 导航属性来为您提供连接,您可以手动进行连接:

    var sites = (from site in context.Sites
                 join p in context.Photos on site.SiteID equals p.SiteId into pj
                 select new {
                     Site = site,
                     Cam1 = pj.Any(p => p.PhotoNumber == 1),
                     Cam2 = pj.Any(p => p.PhotoNumber == 2),
                     Cam3 = pj.Any(p => p.PhotoNumber == 3)
                 }).ToList();
    

    【讨论】:

    • 这个答案可能适用于 LINQ to Objects(甚至适用于 EF Core,谁知道呢)。但是在 EF6 中,它生成的 SQL 与 OP 的原始查询完全相同,因此没有任何区别。如果使用导航属性而不是组加入,则相同。一个很好的例子,说明您如何不能简单地将一般原则应用于具体场景。
    • 我印象深刻的是 EF/LINQ to SQL 将 into pj 转换为子选择查询并且不通过连接。希望 SQL Server 将创建一个有效的计划。
    【解决方案3】:

    如果您只想知道每个网站的每张照片是否存在,您可以加入一次并透视结果:

    var sites =
        from site in context.Sites
        join photo in context.Photos on site.Id equals photo.SiteId into photos
        from photo in photos.DefaultIfEmpty()
        group photo by site into g
        select new
        {
            Site = g.Key,
            HasPhotoNumber1 = g.Any(x => x.PhotoNumber == 1),
            HasPhotoNumber2 = g.Any(x => x.PhotoNumber == 2),
            HasPhotoNumber3 = g.Any(x => x.PhotoNumber == 3)
        };
    

    执行单个LEFT OUTER JOIN 会更高效,并确保结果中仍返回没有任何照片的站点。

    另外,请确保 SiteId 已编入索引。例如:

    CREATE UNIQUE NONCLUSTERED INDEX [IX_Photos] ON [Photos]
    (
       [SiteId] ASC,
       [PhotoNumber] ASC
    );
    

    【讨论】:

      猜你喜欢
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      • 2015-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-25
      相关资源
      最近更新 更多