简体   繁体   中英

Subqueries in linq instead of recursion

I have a nested structure.

Class Page have ChildPages

class Page
{
 IQueryable<Page> ChildPages;
 string type; //catalog or product
}

I need get I should get a request for a sample of all products (type=="product") in all subcategories (type=="catalog") .

it is easy to do with loops and recursion. but it takes a lot of time and resources

我认为EF不支持该功能,但是您可以使用递归CTE查询在一个数据库调用中检索整个树。

The only way I know to do recursive Linq is to use a Fixpoint operator (see below)

But I doubt EF will be able to convert this to a CTE query ( see @erikkallen answer ), which is the only way I know to do recursive query in one statement.

class Page
{
    IQueryable<Page> ChildPages;
    string type; //catalog or product

    // the query
    static IQueryable<Page> GetProductsWithCatalogAncestor(IQueryable<Page> pages)
    {
        return FixPoint<bool, IQueryable<Page>, IQueryable<Page>>
            (processChildPages => (hasCatalogAncestor, thePages) 
                => thePages.SelectMany(p => (hasCatalogAncestor && p.type == "product" ) 
                    ? new[] { p }.AsQueryable()
                    : processChildPages(hasCatalogAncestor || p.type == "catalog", p.ChildPages)))
                    (false, pages);
    }

    // Generic FixPoint operator
    static Func<T1, T2, TResult> FixPoint<T1, T2, TResult>(Func<Func<T1, T2, TResult>, Func<T1, T2, TResult>> f)
    {
        return (t1, t2) => f(FixPoint(f))(t1, t2);
    }
}

Try using SelectMany() to flatten the hierarchy.

var data = pages.SelectMany(p=>p.ChildPages)
                .Where(p=>p.type == "product" || p.type == "catalog");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM