LINQ:选择一个类别下的产品,包括子类别
下面的代码搜索匹配关键字s
或处于与关键字s
匹配的类别下的产品。LINQ:选择一个类别下的产品,包括子类别
这是工作但繁琐,我想知道是否有一个更短的方法来做到这一点?
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()
这样的函数。
我现在不需要表达式,因为这段代码只用了一次。
在linq中没有任何递归查询的捷径,在linq中没有什么捷径可以通过SQL查询提供程序来支持。但是,在执行之前,有一条声明先被转换为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返回产品的所有类别。
使用EF的另一种方法是使用while循环简单查询子类别的所有类别。
完成后,您将拥有所有ID。第一次,查询计划尚未完成,它需要一段时间,但它的速度非常快,取决于数据库的怪异程度。
然后,你可以query for all products that have any of a list of category IDs使用Contains
方法被翻译成WHERE FieldName IN (1,2,3)
这种方法的优点是,它不依赖于你有子类别的多少级。它始终有效,而另一种替代方式默默无闻。
看起来应该在数据库中创建一个View来获取有关类别(使用公共表表达式)的分层数据并使用该View进行查询,而不是'Category'表本身。 – MarcinJuraszek 2013-04-04 05:50:02