以下代码搜索与关键字s
匹配或位于与关键字s
匹配的类别下的产品。
它工作但很乏味,我想知道是否有更短的方法来做到这一点?
var products = context.Products.Where(x =>
x.Name.Contains(s) ||
x.Products_Categories.Any(pc =>
pc.Category.Name.Contains(s) ||
(pc.Category.Category1 != null && pc.Category.Category1.Name.Contains(s)) ||
(pc.Category.Category1 != null && pc.Category.Category1.Category1 != null && pc.Category.Category1.Category1.Name.Contains(s) ||
(pc.Category.Category1 != null && pc.Category.Category1.Category1 != null pc.Category.Category1.Category1.Category1 != null && &&pc.Category.Category1.Category1.Category1.Name.Contains(s))
);
如果不明显:
Products_Categories
是多对多关系,Product
可以在一个或多个Category
中。
Category1
是Category
的父类别。
请注意,它已链接到数据库,因此我无法使用IsUnderCategory()
等功能
我目前不需要Expression,因为这段代码只使用一次。
答案 0 :(得分:1)
在linq中没有递归查询的快捷方式,在SQL查询提供程序支持的linq中则不那么快。但是,在执行之前,语句首先被转换为SQL 的一个优点:SQL没有空引用的概念。因此,您从语句中删除所有null
个检查:
var products = context.Products.Where(x =>
x.Name.Contains(s) ||
x.Products_Categories.Any(pc =>
pc.Category.Name.Contains(s) ||
pc.Category.Category1.Name.Contains(s) ||
pc.Category.Category1.Category1.Name.Contains(s) ||
pc.Category.Category1.Category1.Category1.Name.Contains(s))
);
它将被转换为具有许多外连接的SQL语句。正如您所知,如果在没有记录的情况下处理外连接表的字段,SQL不会崩溃。
查询将是......怪异的。而且你必须假设层次结构的最大深度。改进的唯一方法是在数据库中创建一个视图,该视图按recursive SQL query返回产品的所有类别。
答案 1 :(得分:0)
使用EF的另一种方法是使用while循环简单地查询子类别的所有类别。
完成后,您拥有所有ID。第一次,查询计划还没有完成,需要一点时间,但是它的速度非常快,具体取决于您的数据库是多么可怕。
然后您可以query for all products that have any of a list of category IDs使用转化为Contains
的{{1}}方法
这种方法的优点在于它不依赖于您拥有多少级别的子类别。它始终有效,而另一种选择无声地失败。