LINQ to Entities Any() and Contains() slow with small list

前端 未结 2 746
借酒劲吻你
借酒劲吻你 2021-01-22 08:37

I\'m using EF 6 to get products from a database. The product categories are mapped as a navigation property on products, and the data is from a ProductCategory pivot table. The

相关标签:
2条回答
  • 2021-01-22 08:45

    Try first filtering out the products and only then forming your models (Product_PL and Category_PL):

    var filteredProducts = db.Products.Where(p => p.Categories.Any(c => currentCategoryIdAndChildren.Contains(c.ID)))
        .Select(p => new Product_PL
        {
            id = p.ID,
            name = p.Name,
            description = p.Description,
            categories = p.Categories
                        .Select(c => new Category_PL
                        {
                            categoryid = c.ID,
                        }),
        });
    
    0 讨论(0)
  • 2021-01-22 09:12

    I tried many different things and finally found a solution.

    I believe the main slowdown happened when EF was translating the Contains() into a SQL query. The most noticeable thing, however, was that it did not appear to cache the query. From what I can gather, this is because the list of category IDs (currentCategoryIdAndChildren) was generated outside of EF, so it assumed it would be different every time.

    I was able to speed things up by using the PredicateBuilder in LINQKit. This allowed me to create the logic more explicitly:

    var IsInCategory = PredicateBuilder.False<Product_PL>();
    
    foreach (int categoryID in currentCategoryIdAndChildren)
    { IsInCategory = IsInCategory.Or(pl => pl.categories.Any(c => categoryID == c.categoryid)); }
    
    products = products.Where(IsInCategory);
    

    This got me a bit better performance with my initial query, and MUCH better performance with subsequent queries.

    0 讨论(0)
提交回复
热议问题