如何根据parent的属性高效过滤children
How to efficiently filter children based on parent's attribute
我正在寻求有关构建搜索栏的帮助。我这里有 3 个数据库 table:Case
-> Exhibit
-> Tasking
。 Case
是 Exhibit
的 parent 而 Exhibit
是 Tasking
的 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;
}
在不了解问题的更多细节的情况下,很难得出明确的答案,但可以通过以下方法进行改进:
- 尝试将此作为一个可以转换为 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 很难、不可能或违背你的架构哲学,那么首先质疑你的架构哲学,但你仍然可以通过以下方式使事情稍微好一些:
_dbContext.Exhibits.ToList()
和 _dbContext.Cases.ToList()
在开始之前循环。这样,所有 Case
s 和所有 Exhibit
s 都将被数据库上下文跟踪,并且循环内的 Find() 不会引发数据库往返。但是,这可能无法扩展,因为实例数可能太高了。
我正在寻求有关构建搜索栏的帮助。我这里有 3 个数据库 table:Case
-> Exhibit
-> Tasking
。 Case
是 Exhibit
的 parent 而 Exhibit
是 Tasking
的 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;
}
在不了解问题的更多细节的情况下,很难得出明确的答案,但可以通过以下方法进行改进:
- 尝试将此作为一个可以转换为 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 很难、不可能或违背你的架构哲学,那么首先质疑你的架构哲学,但你仍然可以通过以下方式使事情稍微好一些:
_dbContext.Exhibits.ToList()
和_dbContext.Cases.ToList()
在开始之前循环。这样,所有Case
s 和所有Exhibit
s 都将被数据库上下文跟踪,并且循环内的 Find() 不会引发数据库往返。但是,这可能无法扩展,因为实例数可能太高了。