2

Contents というテーブルがあります。Contents には 1 対多の関係があるため、各コンテンツは親と子を持つことができます。私は EF Code First を使用しているので、 、、およびプロパティContentを持つエンティティがあります。IdParentIdParentChildren

今、私はコンテンツの ajax ベースのツリーを構築しています。以下に基づいて、コンテンツの 1 つのレベルの JSON を返す単純なアクションがありますparentId

public JsonResult GetContents(int? parentId = null)
{
    return Json(db.Contents
        .Where(p => p.ParentId == parentId)
        .Select(p => new
        {
            id = p.Id,
            name = p.Name
        });
}

次にやりたいことは、何らかの値を自動的に選択することです。問題は、値がツリーの階層の奥深くにある可能性があることです。そのため、コンテンツごとに、選択した値がその子であるか孫であるかなどを知る必要があります。

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は私が知る限り再帰的なメソッドを提供していないので、どこから始めればいいのか本当にわかりません.

4

1 に答える 1

1

最初に、選択した値からすべての ParentIds のリストを作成できます。Contents テーブルのサイズによっては、最初にデータをロードしてから、データベースに追加のクエリを実行せずにループすることができます。

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 (Common Table Expression) を使用することもできます。

var parents = db.Database.SqlQuery<int>("sql statement");

親のリストを取得したら、 を使用できますContains

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

更新: 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();
于 2013-08-22T18:56:52.320 に答える