EF Core One-to-Many Linq查询

n3h0vuf2  于 2024-01-03  发布在  其他
关注(0)|答案(1)|浏览(193)

我有两个实体之间的一对多关系,需要查询这两个实体的组合。
一个是File模型:

  1. public class FileMetadata
  2. {
  3. [Key]
  4. public int Id { get; set; }
  5. public string Name { get; set; }
  6. public string Category { get; set; } = string.Empty;
  7. public string Description { get; set; } = string.Empty;
  8. public string UserName { get; set; }
  9. public DateTime UploadDate { get; set; }
  10. public int FileContentId { get; set; }
  11. public FileContent Content { get; set; }
  12. public int UserId { get; set; }
  13. public User User { get; set; }
  14. }

字符串
另一个是Tag模型:

  1. public class FileTag
  2. {
  3. [Key]
  4. public int Id { get; set; }
  5. public string Text { get; set; }
  6. public int FileMetadataId { get; set; }
  7. public FileMetadata Metadata { get; set; }
  8. }


这种关系的本质是,一个文件可以有一对多的标签。我需要做的是实现一个搜索方法,可以搜索文件的内容(描述,名称等),但 * 也 *,搜索该文件的所有标签。这就是问题所在,我找不到一个 * 有效 * 的方法来做到这一点。
这就是我到目前为止所做的,它给了我预期的结果,但是,它不是有效的:

  1. public async Task<ServiceResponse<FileSearchResult>> SearchFileMetaData(string searchText, int page, float resultsPerPage)
  2. {
  3. var pageCount = Math.Ceiling((await FindFilesBySearchText(searchText)).Count / resultsPerPage);
  4. //Add tags to descriptions
  5. var extendedFiles = _context.Files.ToList();
  6. var tags = _context.FileTags.ToList();
  7. foreach (var file in extendedFiles)
  8. {
  9. var thisFilesTags = tags.Where(t => t.FileMetadataId == file.Id).ToList();
  10. foreach (var tag in thisFilesTags)
  11. {
  12. file.Description += tag.Text;
  13. }
  14. }
  15. //Search files with metadata matching the search text.
  16. var files = extendedFiles
  17. .Where(f => f.Name.ToLower().Contains(searchText.ToLower())
  18. || f.Description.ToLower().Contains(searchText.ToLower()))
  19. .Skip((page - 1) * (int)resultsPerPage)
  20. .Take((int)resultsPerPage)
  21. .ToList();
  22. var response = new ServiceResponse<FileSearchResult>
  23. {
  24. Data = new FileSearchResult
  25. {
  26. Files = files,
  27. ThisPageNumber = page,
  28. TotalPages = (int)Math.Floor(pageCount)
  29. }
  30. };
  31. return response;
  32. }


我从数据库中获取 * 所有 * 文件和标记,循环使用File实体的标记构建描述字段,然后执行Linq操作过滤搜索文本。
我如何才能仍然得到预期的结果,但提高性能,而不是得到不必要的记录?
另外,这个问题是否可以用一个更好的Linq查询来解决,它可以连接这两个实体?或者,关系/表是否需要重新定义?

oaxa6hgo

oaxa6hgo1#

尝试以下查询。它试图在物化之前过滤掉文件。为了确定这不是理想的解决方案,Contains执行全表扫描,如果表太大,可能会影响性能。

  1. public async Task<ServiceResponse<FileSearchResult>> SearchFileMetaData(string searchText, int page, float resultsPerPage)
  2. {
  3. searchText = searchText.ToLower();
  4. var filesQuery = _context.Files
  5. .Where(f => f.Name.ToLower().Contains(searchText)
  6. || f.Description.ToLower().Contains(searchText)
  7. || _context.FileTags.Any(t => t.FileMetadataId == f.Id && t.Text.ToLower().Contains(searchText))
  8. );
  9. var pageCount = Math.Ceiling((await filesQuery.CountAsync()) / resultsPerPage);
  10. var files = filesQuery
  11. .Skip((page - 1) * (int)resultsPerPage)
  12. .Take((int)resultsPerPage)
  13. .AsNoTracking()
  14. .ToList();
  15. var response = new ServiceResponse<FileSearchResult>
  16. {
  17. Data = new FileSearchResult
  18. {
  19. Files = files,
  20. ThisPageNumber = page,
  21. TotalPages = (int)Math.Floor(pageCount)
  22. }
  23. };
  24. return response;
  25. }

字符串

展开查看全部

相关问题