如何使用Entity Framework有效地查询存储在数据库中的树结构?

时间:2015-05-21 20:32:37

标签: c# asp.net-mvc performance linq

我有一个可以相互关联的元素表(在同一个表中)。

例如,结构如:

[Id]                      Int 
[ParentWithinThisTableId] Int
[AFieldToQueryAgainst]    NVarCharMax

在搜索开始时,我将获得一个字符串查询和一个Id(称之为StartId,指向此表中的元素。我想要做的是将字符串查询与对于给定Id的元素,[AFieldToQueryAgainst],但是对于具有[ParentWithinThisTableId] == StartId的所有行,然后查询具有这些 ID的所有行的同一列,[ParentWithinThisTableId]为{{ 1}}。

我能想到的唯一方法是递归地像:

    var forms = db.Forms.Where(m => m.ParentWithinThisTableId == this.Id);

    var searchMatches = new List<Form>();

    foreach (var form in forms)
    {
        forms = forms.Concat(AddSearches(query, form.Id));
    }

    foreach (var form in forms)
    {
        if (form.AFieldToQueryAgainst.Contains(query))
        {
            searchMatches.Add(form);
        }
    }

AddSearches递归,如:

    private IQueryable<Form> AddSearches(string query, int startId)
    {
        var items = RepositoryProxy.Context.Forms.Where(m => m.ParentWithinThisTableId == startId);

        foreach (var item in items)
        {
            items = items.Concat(AddSearches(query, item.Id));
        }

        return items;
    }

但是在我相对较浅的树上进行测试时,这需要大约1.8秒的运行时间。有没有更有效的方法来做到这一点?可能会避免迭代每个IQueryables,直到它们以某种方式编译完成?

1 个答案:

答案 0 :(得分:0)

为什么你不能使用自我加入?

var these = (from p in items
                join x in items on p.Id equals x.ParentId
                where x != null
                select x).ToList();