Asp.net mvc 实体框架-如何检查一个对象是否在另一个对象的层次结构下?
我有一张叫做目录的表格。内容上存在一对多关系,因此每个内容都可以有父项和子项。我首先使用EF代码,所以我有一个实体内容,它有Id、ParentId、Parent和Children属性 现在,我正在构建一个基于ajax的内容树。我有一个简单的操作,返回一个基于parentId的一级内容的JSON: 我想做的下一件事是自动选择一些值。问题是,该值可能深入到树的层次结构中,因此对于每个内容,我需要知道所选值是否是它的子对象或孙子对象等等Asp.net mvc 实体框架-如何检查一个对象是否在另一个对象的层次结构下?,asp.net-mvc,entity-framework,Asp.net Mvc,Entity Framework,我有一张叫做目录的表格。内容上存在一对多关系,因此每个内容都可以有父项和子项。我首先使用EF代码,所以我有一个实体内容,它有Id、ParentId、Parent和Children属性 现在,我正在构建一个基于ajax的内容树。我有一个简单的操作,返回一个基于parentId的一级内容的JSON: 我想做的下一件事是自动选择一些值。问题是,该值可能深入到树的层次结构中,因此对于每个内容,我需要知道所选值是否是它的子对象或孙子对象等等 public JsonResult GetContents(in
public JsonResult GetContents(int? parentId = null, int selectedValue)
{
return Json(db.Contents
.Where(p => p.ParentId == parentId)
.Select(p => new
{
id = p.Id,
name = p.Name
isSelectedValueUnderThisHierarchy: // How can I efficiently implement this?
});
}
使用大量查询很容易实现,但我正在努力使事情尽可能高效,而且据我所知,EF不提供任何递归方法,因此我真的不知道从哪里开始。您可以首先根据所选值构建所有ParentID的列表。根据内容表的大小,您可以先加载数据,然后循环,而无需对数据库进行额外查询
db.Contents.Load();
var selectedItem = db.Contents.Find(selectedValue);
var parents = new List<int>();
while (selectedItem.ParentId != null)
{
parents.Add(selectedItem.ParentId.Value);
selectedItem = selectedItem.Parent;
}
更新:CTE示例
您可能希望使用存储过程,但这段代码应该可以工作
var sql = @"with CTE as
(
select ParentId
from Contents
where Id = {0}
union all
select Contents.ParentId
from Contents
inner join CTE on Contents.Id = CTE.ParentId
)
select *
from CTE
where ParentId is not null";
var parents = db.Database.SqlQuery<int>(string.Format(sql, selectedItem)).ToList();
我不知道如何在没有循环函数的情况下做到这一点,但是,我想指出的是,您不应该将p.ParentId与null进行比较,这是默认参数中的操作抱歉,我忘了提到它是一个零或一对多关系,而不仅仅是一对多关系,所以如果一个项没有父项,ParentId=null。这就是为什么你不应该和我比较null@MichaelCwienczek谢谢,我不知道这个表很大,所以我不能全部加载。你可以使用CTE,它只会在一次查询中从数据库中返回ID。我将用一个例子更新我的答案。
var parents = db.Database.SqlQuery<int>("sql statement");
return Json(db.Contents
.Where(p => p.ParentId == parentId)
.Select(p => new
{
id = p.Id,
name = p.Name
isSelectedValueUnderThisHierarchy = p.ParentId.HasValue && parents.Contains(p.ParentId.Value)
});
var sql = @"with CTE as
(
select ParentId
from Contents
where Id = {0}
union all
select Contents.ParentId
from Contents
inner join CTE on Contents.Id = CTE.ParentId
)
select *
from CTE
where ParentId is not null";
var parents = db.Database.SqlQuery<int>(string.Format(sql, selectedItem)).ToList();