原来的帖子问题已经老了,但我最近多次遇到这个问题,并找到了可能对其他人有帮助的解决方案。而且,由于上述答案都没有给出 NHibernate 代码的答案,我也认为这与帖子有关。
在我们的软件产品中,用户在用户界面中进行选择。然后前端将对应的 id 列表传递给后端进行数据查询和操作。
首先,我需要一个函数来将元素列表拆分为 1000 个元素的分区。
注意,这是 VB.NET,但函数本身在 C# 的 StackOverflow 上的其他地方找到:
Public Shared Iterator Function Partition(Of T)(source As IList(Of T), Optional size As Int32 = 1000) As IEnumerable(Of List(Of T))
For i As Integer = 0 To CInt(Math.Ceiling(source.Count / CDbl(size)))
Yield New List(Of T)(source.Skip(size * i).Take(size))
Next
End Function
这个函数我用过好几种方式。一种方法是遍历列表分区以修改 QueryOver 以将所有部分结果合并,如下所示:
Dim allPartitions As IEnumerable(Of List(Of Integer)) = Partition(idList, SplitSize)
Dim foundObjects As IEnumerable(Of MyEntity) = New List(Of MyEntity)
For Each part As List(Of Integer) In allPartitions
foundObjects = foundObjects.Union(
_session.QueryOver(Of MyEntity) _
WhereRestrictionOn(Function(x) x.ID).IsIn(part).Future())
Next
我使用的另一种方法是创建一个限制,可以在 QueryOvers 中应用。以下函数创建了这样一个限制(ICriterion):
Public Shared Function GetRestrictionOnIds(ids As List(Of Integer), propertyName As String) As ICriterion
Dim allParts As IEnumerable(Of List(Of Integer)) = Partition(ids, SplitSize)
Dim restriction As Disjunction = Restrictions.Disjunction()
For Each part As List(Of Integer) In allParts
restriction.Add(Restrictions.In(propertyName, part))
Next
Return Restrictions.Conjunction().Add(restriction)
End Function
我这样称呼那个函数:
Dim wellIdRestriction As ICriterion = GetRestrictionOnIds(wellIdsList, "WellId")
Dim bleedOffs As IList(Of BleedOff) = _session.QueryOver(Of BleedOff)() _
.Where(wellIdRestriction) _
.Where(..... more restrictions...) _
.And(...yet more restrictions....) _
.List().GroupBy(...some function...) _
.ToDictionary(.. key-function, value-function...)