类别和子类别在C#/ LINQ和放大器; SQL [英] categories and sub-categories in c# / linq & sql

查看:149
本文介绍了类别和子类别在C#/ LINQ和放大器; SQL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我建立一个asp.net网站使用MS-SQL数据库产品 - 每个产品属于一个或多个类别,每个类别可以属于一个或零父类别。

用户应当能够选择零个或多个类别,但我不能想出一个办法只返回产品在选定的类别。

这是工作

我已经得到了其他过滤器(最低价格,品牌等),但不能'得到的类别的工作。

例如:

   - 类别1
| ---子类别1.1
    | ---子子类别1.1.1
    | ---子子类别1.1.2| ---子类别1.2| ---子类别1.3

如果第1类被选中,然后有一个类别,其中最终母公司为第1类应返回的所有产品。

如果选择子类别1.1和子类别1.2,则有一个类别,其中最终母公司或者是子类别1.1或子类别1.2应返回的所有产品。

这是我的code:

产品:

 公共类产品
{
    [键]
    公众诠释的ProductID {搞定;组; }
    公共字符串描述{获取;设置;}
    公共双价{获取;设置;}    公共虚拟目录<类别及GT;分类{搞定;组; }    公共产品()
    {
       分类=新的List<类别及GT;();
    }}

类别:

 公共类分类
{
    [键]
    公众诠释类别ID {搞定;组; }
    公共字符串类别名称{搞定;组; }    公众诠释? ParentCategoryID {搞定;组; }    [JsonIgnore]
    公共范畴家长{搞定;组; }    [JsonIgnore]
    公共虚拟目录<产品与GT;产品{搞定;组; }}

简体的WebAPI控制器:

 公共对象获取([FromUri]字符串[]类别)
{
    清单<产品与GT; sea​​rch_results =(从db.Products p
        其中1 == 1
              &功放;&安培; p.Price> = minPrice和放大器;&安培; p.Price< = maxPrice
             //只返回产品在选定的类别      选择P).ToList();}


解决方案

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

 公共对象获取([FromUri]字符串[]类别)
{
    VAR类别= db.Categories.Where(C => categoriesIds.Contains(c.Id));
    FUNC<产品,布尔>过滤器= P => 1 == 1
          &功放;&安培; p.Price> = minPrice和放大器;&安培; p.Price< = maxPrice
    返回GetCategoryiesProducts(类别,过滤器)
}公众的IList<产品与GT; GetCategoryiesProducts(IList的<分类和GT;类,函数功能与LT;产品,布尔>过滤器)
{
    VAR的结果=新的List<产品及GT;();
    的foreach(按类别变种C)
    {
        result.AddRange(c.Products.Where(过滤器).ToList());
        变种子类别= db.Categories.Where(S => s.ParentCategoryID =空&放大器;!及(INT)s.ParentCategoryID == c.Id))
        如果(子类= NULL&放大器;!&安培; subCategories.Count大于0)
        {
             result.AddRange(GetCategoryiesProducts(子类,过滤器))
        }
    }
    清单<产品与GT; sea​​rch_results结果;
}

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

 列表<产品与GT; sea​​rch_results =(从db.Products p
其中1 == 1
    &功放;&安培; p.Price> = minPrice和放大器;&安培; p.Price< = maxPrice
    &功放;&安培; p.Categories.Any(C => categoriesIds.Contains(c.Id))
选择P).ToList();

I am building an asp.net website with ms-sql db for products - each product belongs to one or more categories and each categories can belong to one or zero parent categories.

The user should be able to select zero or many categories, but i can't figure out a way to only return products in the selected categories.

i've got other filters which are working (minimum price, brand name etc) but cant' get the categories to work.

For example:

-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

If Category 1 is selected, then all products that have a category where the Ultimate Parent is Category 1 should be returned.

If Sub-Category 1.1 and Sub-Category 1.2 is selected then all products that have a category where the Ultimate Parent is either Sub-Category 1.1 OR Sub-Category 1.2 should be returned.

This is my Code:

Product:

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>();
    }

}

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; }

}

Simplified WebApi Controller:

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();

}

解决方案

If you have no limits on sub categories, you can use recursion:

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;
}

but if there be a lot of categories it will be expensive solution. To optimize for efficiency you can add product to each parent categories to eliminate recursion:

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();  

这篇关于类别和子类别在C#/ LINQ和放大器; SQL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆