5

获取所选主类别的所有子类别中的所有产品的最佳方法是什么?试图在大约 80 个子类别中获取 10000 个产品,但这种方法太慢了。有什么建议么?使用 c# 和 Linq to SQL

//list for the child categories
private List<int> catsChildList = new List<int>();

GetChildCats(123);

//get all the child categories of main category '123'

private void GetChildCats(int _parentCat)
{
    var cats = (from c in db2.tbl_cart_categories
                where c.ParentID == _parentCat
                select new { c.CategoryID });
    if (cats.Count() > 0)
    {
        foreach (var cat in cats)
        {
            int _cat = Convert.ToInt32(cat.CategoryID);
            catsChildList.Add(_cat);
            GetChildCats(_cat);
        }
    }
}

//Get the products
var products = (from p in db2.products_infos
            where  p.IsEnabled == true
            group p by p.ProdID
            into g where g.Any(x => catsChildList.Contains(Convert.ToInt32(x.CategoryID)))

返回结果大约需要 6 秒

4

4 回答 4

3

和有什么区别

var products = 
    (
     from p in db2.products_infos
     where  p.IsEnabled == true
     group p by p.ProdID
     into g where g.Any(x => catsChildList.Contains(Convert.ToInt32(x.CategoryID)))
     select g
    );

 var tmpList = 
    (
     from p in db2.products_infos
     where  p.IsEnabled == true 
            && catsChildList.Contains(Convert.ToInt32(p.CategoryID))) 
     select p
    ).ToList();

 var products = 
     (from r in tmpList group p by r.ProdID into g select g);

?

也许我的架构不同,但是当我使用 Linq2Sql 尝试此操作时,它似乎返回相同的结果,但后者在一次数据库命中中返回所有结果,而前者发出多个请求。(如果返回的产品数量是 10000,它将执行 10001 个数据库请求)。

于 2012-04-04T17:11:12.767 回答
2

根据提供的统计信息和代码,您应该通过删除此行来节省 3 秒:

if (cats.Count() > 0)

...因为它使枚举加倍(并且鉴于这意味着您将数据库调用加倍,这完全是糟糕的)并且几乎毫无意义,因为如果 Count == 0 之后没有任何东西会崩溃。

如果您使用的是 MS SQL Server,那么他们提供的 Profiler 就是您的朋友,因为您可能会看到额外的数据库命中。

于 2012-04-04T16:06:39.730 回答
0

一种。以下代码行是通过 GetChildCats() 方法替换第一行的 lambda 表达式。

var findCatList = (List<int> parent) => {        
    from c in db2.tbl_cart_categories
            where  & c.ParentID == _parentCat
            select (db2.tbl_cart_categories.Any(cat=> cat.ParentID == c.CategoryID) ?
                findCatList(c.CategoryID)
                :new { c.CategoryID }                    
                )}

var catList = findCatList(123);

但即使这样也会进行递归,但会在内部完成。请检查一下。当然,它只是基于您的对象的未经测试的代码。

湾。其他认为您可以尝试的是,您可以尝试将 db2.tbl_cart_categories 替换为 db2.tbl_cart_categories.AsParallel()。我不确定对象上下文/数据上下文如何处理这个问题。但是 db2 不是上下文对象,那么我相信它会提高性能。

于 2012-04-04T16:28:59.120 回答
0

首先,虽然你没有具体说明,但我假设你使用的是 Linq to Sql。请更新您的问题以包含该信息。

首先添加一些基本的分析。哪个查询运行时间最长?

g.Any(x => catsChildList.Contains(Convert.ToInt32(x.CategoryID)))

这绝对是可疑的。如果catsChildList 有很多值,您可能会生成一个巨大的IN 子句,该子句总是运行缓慢。您可以通过检查正在运行的实际 SQL 语句来验证这一点。

事实是,当您尝试在应用程序中执行每次迭代时,像这样的递归层次结构遍历永远不会有效。使用存储过程将获得更好的性能。

于 2012-04-04T16:32:43.283 回答