如何使用实体框架有效地查询存储在数据库中的树结构



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

例如这样的结构:

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

在搜索开始时,我将得到一个字符串查询和单个Id(称为StartId),它指向该表中的一个元素。我想做的是将字符串查询与给定Id的元素上的[AFieldToQueryAgainst]进行比较,但也对具有[ParentWithinThisTableId] == StartId的所有行查询同一列,然后所有具有这些 Id的行作为[ParentWithinThisTableId]

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

    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,直到它们都以某种方式编译?

为什么不能直接使用self join呢?

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

最新更新