【问题标题】:categories and sub-categories in c# / linq & sqlc#/linq 和 sql 中的类别和子类别
【发布时间】:2015-05-03 11:10:18
【问题描述】:

我正在为产品构建一个带有 ms-sql db 的 asp.net 网站 - 每个产品属于一个或多个类别,每个类别可以属于一个或零个父类别。

用户应该能够选择零个或多个类别,但我想不出一种只返回所选类别中的产品的方法。

我有其他过滤器正在工作(最低价格、品牌名称等),但无法让类别工作。

例如:

-Category 1
|---Sub-Category 1.1
    |---Sub-Sub-Category 1.1.1
    |---Sub-Sub-Category 1.1.2

|---Sub-Category 1.2

|---Sub-Category 1.3

如果选择了类别 1,则应退回具有最终父类别为类别 1 的类别的所有产品。

如果选择了子类别 1.1 和子类别 1.2,则应退回所有最终父类别为子类别 1.1 或子类别 1.2 的产品。

这是我的代码:

产品:

public class Product
{
    [Key]
    public int ProductID { get; set; }
    public string Description {get;set;}
    public double Price {get;set;}

    public virtual List<Category> Categories { get; set; }

    public Product()
    {
       Categories = new List<Category>();
    }

}

类别:

public class Category
{
    [Key]
    public int CategoryID { get; set; }
    public string CategoryName { get; set; }

    public int? ParentCategoryID { get; set; }

    [JsonIgnore]
    public Category Parent { get; set; }

    [JsonIgnore]
    public virtual List<Product> Products { get; set; }

}

简化的 WebApi 控制器:

public object Get(  [FromUri] string[] categories)
{
    List<Product> search_results = (from p in db.Products  
        where 1==1
              && p.Price >= minPrice && p.Price <=maxPrice 
             // only return products in selected categories

      select p).ToList();

}

【问题讨论】:

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


    【解决方案1】:

    如果对子类别没有限制,可以使用递归:

    public object Get(  [FromUri] string[] categories)
    {
        var categories = db.Categories.Where(c => categoriesIds.Contains(c.Id));
        Func<Product, bool> filters = p => 1==1
              && p.Price >= minPrice && p.Price <=maxPrice 
        return GetCategoryiesProducts(categories, filters)
    }
    
    public IList<Product> GetCategoryiesProducts(IList<Category> categories, Func<Product, bool> filters)
    {
        var result = new List<Product>();
        foreach (var c in categories) 
        {
            result.AddRange(c.Products.Where(filters).ToList());
            var subCategories = db.Categories.Where(s => s.ParentCategoryID != null && (int)s.ParentCategoryID == c.Id))
            if (subCategories != null && subCategories.Count > 0)
            {
                 result.AddRange(GetCategoryiesProducts(subCategories, filters))
            }
        }
        List<Product> search_results result;
    }
    

    但如果有很多类别,这将是昂贵的解决方案。为了优化效率,您可以将产品添加到每个父类别以消除递归:

    List<Product> search_results = (from p in db.Products  
    where 1==1
        && p.Price >= minPrice && p.Price <=maxPrice 
        && p.Categories.Any(c => categoriesIds.Contains(c.Id))
    select p).ToList();  
    

    【讨论】:

    • 如果只选择顶级类别,这会起作用吗?例如产品 A 有类别 [1.1.1] 并且用户选择了父类别 [1.1] 产品 A 应该被退回。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 2021-02-19
    • 2015-04-05
    • 1970-01-01
    相关资源
    最近更新 更多