如何根据parent的属性高效过滤children

How to efficiently filter children based on parent's attribute

我正在寻求有关构建搜索栏的帮助。我这里有 3 个数据库 table:Case -> Exhibit -> TaskingCaseExhibit 的 parent 而 ExhibitTasking 的 parent。我有一个 table 显示关于 Taskings 列表的信息以及它们的 parent Id (Exhibit) 和 grandparent Id (Case ).

我希望能够根据 Case ID 搜索 Taskings。这是我当前的解决方案(有效),显示和搜索在 2000 任务下都很慢。

我认为这是因为循环中有 2 个 find 语句。 IsMatchedTasking 也是一个有点复杂的查询,我不能只用 linq 语句来写。

理想情况是将一个查询存储为 IQueryable,它保留所有 parent 关系,并将其传递到搜索中。但是由于我使用的是 PagedList,它会在传递到视图时摆脱 parent 关系。

关于如何正确执行此操作而无需查看数据库上下文 3 次的任何建议(在数据库中查询 Taskings,在数据库中过滤搜索并检查数据库以显示 parents 属性)?

public ActionResult GetNew(int? page, int? pageSize, string searchString)
{
    int pageNumber = page ?? 1;
    var currUser = _userManager.FindByNameAsync(User.Identity.Name).Result;
    var ps = Util.SetSessionPageSize(10, pageSize, HttpContext, "taskingGetNewPageSize");
    var output = new List<TaskingViewModel>();
    foreach (var tsk in _dbContext.Taskings) {
        if (currUser.IsMatchedTasking(tsk, _dbContext)) {
            var ex = _dbContext.Exhibits.Find(tsk.ExhibitId);
            var ca = _dbContext.Cases.Find(ex.ParentCaseId);
            output.Add(new TaskingViewModel
            {
                Tasking = tsk,
                ExhibitId = ex.Id,
                ExhibitName = ex.GetExhibitName(),
                CaseId = ca.Id,
                CasePriority = ca.GetCasePosition(_dbContext.TopTens.ToSortedList(_dbContext)),
            });
        }
    }
    var result = Search(searchString, output);
    return View(result.ToPagedList(pageNumber, pageSize: ps));
}

搜索功能 returns TaskingViewModel 的新 List 匹配案例 ID 与 searchString 使用包含。

public List<TaskingViewModel> Search(string searchString, List<TaskingViewModel> toSearch)
{
    var result = new List<TaskingViewModel>();
    if (String.IsNullOrEmpty(searchString))
        return toSearch;
    foreach(var item in toSearch) {
        if (item.Id.Contains(searchString))
            result.Add(item);
    }
    return result;
}

在不了解问题的更多细节的情况下,很难得出明确的答案,但可以通过以下方法进行改进:

  1. 尝试将此作为一个可以转换为 Sql 的查询。如果 IsMatchedTasking 是可以转换为 sql、 的条件(如果您的实体之间存在导航属性),则这是可能的。所以查询将是这样的:
var output = _dbContext.Taskings.Whete(x => x.UserId == userId)
.Select(x => new TaskingViewModel
            {
                TaskId = x.Id,
                TaskName = x.Name,
                ExhibitId = x.ExhibitionId,
                ExhibitName = ex.Exhibition.Name,
                CaseId = x.CaseId,
                CasePriority = x.Case.Priority,
            }.ToList()

但具体取决于您的业务逻辑。

  1. 如果#1 很难、不可能或违背你的架构哲学,那么首先质疑你的架构哲学,但你仍然可以通过以下方式使事情稍微好一些:_dbContext.Exhibits.ToList()_dbContext.Cases.ToList() 在开始之前循环。这样,所有 Cases 和所有 Exhibits 都将被数据库上下文跟踪,并且循环内的 Find() 不会引发数据库往返。但是,这可能无法扩展,因为实例数可能太高了。