EF Core One-to-Many Linq查询

n3h0vuf2  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(138)

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

public class FileMetadata
    {
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; } = string.Empty;
        public string Description { get; set; } = string.Empty;
        public string UserName { get; set; }
        public DateTime UploadDate { get; set; }
        public int FileContentId { get; set; }
        public FileContent Content { get; set; }
        public int UserId { get; set; }
        public User User { get; set; }
    }

字符串
另一个是Tag模型:

public class FileTag
    {
        [Key]
        public int Id { get; set; }
        public string Text { get; set; }
        public int FileMetadataId { get; set; }
        public FileMetadata Metadata { get; set; }
    }


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

public async Task<ServiceResponse<FileSearchResult>> SearchFileMetaData(string searchText, int page, float resultsPerPage)
    {
        var pageCount = Math.Ceiling((await FindFilesBySearchText(searchText)).Count / resultsPerPage);

        //Add tags to descriptions
        var extendedFiles = _context.Files.ToList();
        var tags = _context.FileTags.ToList();

        foreach (var file in extendedFiles)
        {
            var thisFilesTags = tags.Where(t => t.FileMetadataId == file.Id).ToList();
            foreach (var tag in thisFilesTags)
            {
                file.Description += tag.Text;
            }
        }

        //Search files with metadata matching the search text.
        var files = extendedFiles
                        .Where(f => f.Name.ToLower().Contains(searchText.ToLower())
                        || f.Description.ToLower().Contains(searchText.ToLower()))
                        .Skip((page - 1) * (int)resultsPerPage)
                        .Take((int)resultsPerPage)
                        .ToList();

        var response = new ServiceResponse<FileSearchResult>
        {
            Data = new FileSearchResult
            {
                Files = files,
                ThisPageNumber = page,
                TotalPages = (int)Math.Floor(pageCount)
            }
        };
        return response;
    }


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

oaxa6hgo

oaxa6hgo1#

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

public async Task<ServiceResponse<FileSearchResult>> SearchFileMetaData(string searchText, int page, float resultsPerPage)
{
    searchText = searchText.ToLower();

    var filesQuery = _context.Files
        .Where(f => f.Name.ToLower().Contains(searchText)
            || f.Description.ToLower().Contains(searchText)
            || _context.FileTags.Any(t => t.FileMetadataId == f.Id && t.Text.ToLower().Contains(searchText))
        );

    var pageCount = Math.Ceiling((await filesQuery.CountAsync()) / resultsPerPage);

    var files = filesQuery
        .Skip((page - 1) * (int)resultsPerPage)
        .Take((int)resultsPerPage)
        .AsNoTracking()
        .ToList();

    var response = new ServiceResponse<FileSearchResult>
    {
        Data = new FileSearchResult
        {
            Files = files,
            ThisPageNumber = page,
            TotalPages = (int)Math.Floor(pageCount)
        }
    };

    return response;
}

字符串

相关问题