【问题标题】:Search method joing multiple tables连接多个表的搜索方法
【发布时间】:2016-12-10 21:31:21
【问题描述】:

我需要有关在表格中搜索匹配文本的搜索方法的帮助。 这可行,除了联接需要是 LEFT OUTER JOIN 否则如果任何表中缺少 pageId,我都不会得到任何结果。

此解决方案需要很长时间才能运行,如果有人可以帮助我提供更好的解决方案来处理此任务,我将不胜感激。

public async Task<IEnumerable<Result>> Search(string query)
    {

        var temp = await (from page in _context.Pages
                          join pageLocation in _context.PageLocations on page.Id equals pageLocation.PageId
                          join location in _context.Locations on pageLocation.LocationId equals location.Id
                          join pageSpecialty in _context.PageSpecialties on page.Id equals pageSpecialty.PageId
                          join specialty in _context.Specialties on pageSpecialty.SpecialtyId equals specialty.Id

                          where
                              page.Name.ToLower().Contains(query)
                              || location.Name.ToLower().Contains(query)
                              || specialty.Name.ToLower().Contains(query)
                          select new Result
                          {
                              PageId = page.Id,
                              Name = page.Name,
                              Presentation = page.Presentation,
                              Rating = page.Rating
                          }).ToListAsync();

        var results = new List<Result>();

        foreach (var t in temp)
        {
            if (!results.Exists(p => p.PageId == t.PageId))
            {
                t.Locations = GetLocations(t.PageId);
                t.Specialties = GetSpecialties(t.PageId);
                results.Add(t);
            }
        }

        return results;
    }

【问题讨论】:

  • 你为什么加入?没有Page.PageLocations之类的导航属性吗?
  • @GertArnold 不,我只是一个没有导航属性的普通 poco 对象。你的意思是,如果我有导航属性,我就不必加入?
  • 是的,我就是这个意思。强烈推荐。如果您有它们,则对大多数谓词使用Any 会更容易。
  • @GertArnold 好的,你能给我举个例子,说明在使用导航属性和任何属性时该方法的外观吗?谢谢

标签: c# linq search entity-framework-core


【解决方案1】:

使用导航属性,查询可能如下所示:

var temp = await (from page in _context.Pages
                  where Name.Contains(query)
                     || page.PageLocation.Any(pl => pl.Location.Name.Contains(query))
                     || page.PageSpecialties.Any(pl => pl.Specialty.Name.Contains(query))
                 select new Result
                  {
                      PageId = page.Id,
                      Name = page.Name,
                      Presentation = page.Presentation,
                      Rating = page.Rating,
                      Locations = page.PageLocation.Select(pl => pl.Location),
                      Specialties = page.PageSpecialties.Select(pl => pl.Specialty)
                  }).ToListAsync();

这有几个好处:

  1. 由于没有连接,查询会立即返回唯一的 Result 对象,因此您无需在之后对其进行重复数据删除。
  2. 位置和专业加载在同一个查询中,而不是每个 Result 的两个查询(又名 n+1 问题)。
  3. (可能)ToLower 被删除,因为搜索可能不区分大小写。查询作为 SQL 执行,并且大多数情况下,SQL 数据库具有不区分大小写的排序规则。删除 ToLower 会再次生成查询 sargable

【讨论】:

  • 我不能让它工作,你写方法的方式。当前上下文中不存在名称。您的意思是“page.Name.Contains(query)”吗?
  • 请将Page 类添加到您的问题中(包括导航属性)。
猜你喜欢
  • 2015-11-04
  • 2019-02-26
  • 2016-01-09
  • 2014-05-14
  • 1970-01-01
  • 1970-01-01
  • 2012-05-23
  • 1970-01-01
  • 2012-12-19
相关资源
最近更新 更多