我已经建立了一个代表类别树,以帮助进行分类一些我们所储存的数据的数据库结构的所有后代项目。实现方式是Category
表中的每条记录都有一个可为空的外键,返回到Category
表中,以表示此类别(一对多)的父Category
,基本上允许更广泛的父级别中的子类别。有一个CategoryMembership
表,它将Item
表中的记录链接到其各自的Category
(多对多)。我创建该数据库的DBML,它具有包括以下成员访问结构:
Dim aCategory As New Category()
Dim aParentCategory As Category = aCategory.Parent
Dim aChildCategoryCollection As EntitySet(Of Category) = aCategory.Subcategories
Dim aMembershipCollection As EntitySet(Of CategoryMembership) = aCategory.CategoryMemberships
在aMembershipCollection
每一个项目都有以下成员访问结构:
Dim aMembership As CategoryMembership = aMembershipCollection.First()
Dim aLinkedCategory As Category = aMembership.Category
Dim aLinkedItem As Item = aMembership.Item
的要求
我正在尝试构建一个LINQ表达式,该表达式允许我确定哪个Items
具有CategoryMemberships
用于请求的Category
(即aCategory.id = myID
)或所请求的Category
的后代的成员身份,这个想法是我希望所有Items
位于父类别或其多个子类别级别中。
本质上查询将建在类似的方式:
Dim results As IQueryable(Of Item) = _
From cm In db.CategoryMemberships.Where(myInCategoryPredicate(myID)) _
Select cm.Item
...其中myInCategoryPredicate
返回LINQ表达的对象,这将有助于我作出这样的决定。这当然是基于假设CategoryMembership
表是开始检索IQueryable(Of Item)
的地方。我可能在这里做了一个错误的假设,这就是我寻求建议的原因。
的问题
我有一个很难只见树木不见森林。我无法确定是应该从Category还是从CategoryMembership开始构建谓词,也不能确定能够实现我想要的内容的必需代码。我希望已经为数据库构建了类似树结构的其他人可能能够帮助我导航DBML类。
可用资源
我以前发了过去使用的PredicateBuilder和我比较熟悉它的工作原理,但我一直没能想出一个办法,通过树向上遍历,并建立一个谓语递归地表明项目是否在所请求的类别或其子类别中。到目前为止,我已经产生了以下,具有非常明显的差距标记SomeRecursiveCall():
Private Function InCategory(ByVal myID As Integer) As Expression(Of Func(Of CategoryMembership, Boolean))
Dim predicate = PredicateBuilder.False(Of CategoryMembership)()
predicate = predicate.Or(Function(cm) cm.fkCategoryID = myID OrElse SomeRecursiveCall())
Return predicate
End Function
不过,我认识到,一个谓词建设者可能是没有用的,在这里和任何可能需要不同的方向。
我认为总会有选择Category
纪录被请求的ID,并从中建立ID的列表和Subcategories
所有成员递归然后使用该名单,以评估对一。载有()比较的可能性名单,但我想知道是否没有其他选项不那么难受。
我讨厌听到“你不能这样做”,但我理解你的意思。这是一个失望,我不能只是禁用延迟执行,以便允许数据限制。不幸的是,编程解决方案为我最终确定的.Any()重载引发了一个不支持的异常,这会导致我想要的行为(如您所示)。感谢您指点我CTE。一旦完成,我将发布存储过程的结果。 – lsuarez 2011-03-08 05:56:44