Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 实体框架-如何检查一个对象是否在另一个对象的层次结构下?_Asp.net Mvc_Entity Framework - Fatal编程技术网

Asp.net mvc 实体框架-如何检查一个对象是否在另一个对象的层次结构下?

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

我有一张叫做目录的表格。内容上存在一对多关系,因此每个内容都可以有父项和子项。我首先使用EF代码,所以我有一个实体内容,它有Id、ParentId、Parent和Children属性

现在,我正在构建一个基于ajax的内容树。我有一个简单的操作,返回一个基于parentId的一级内容的JSON:

我想做的下一件事是自动选择一些值。问题是,该值可能深入到树的层次结构中,因此对于每个内容,我需要知道所选值是否是它的子对象或孙子对象等等

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();