我尝试使用NHibernate为Kendo's dropdownlist/combobox virtualization实现通用服务器端逻辑。简而言之,他们将选定的ID发送到服务器,并期望在整个数据集中返回此ID的行索引,这在SQL中可以通过ROW_NUMBER实现。
我将用实体'产品'给出我的例子。 我的想法是构造3个嵌套查询的查询:
1。 大多数内部查询将返回1列 - 通过给定过滤器的所有产品ID(仅限活动产品):
SQL:
SELECT PRODUCT_ID FROM PRODUCT
WHERE STATUS = 0
NH:
var innerCriteria = ...;
innerCriteria.SetProjection(Projections.Property("Id"));
备注:此处innerCriteria
以特定方式构建,对于此问题并不感兴趣。
2。 中间查询,它将使用ROW_NUMBER为先前查询中的所有返回产品ID放置行号(中间查询将返回2列:行号和ID):
SQL:
SELECT (ROW_NUMBER() OVER(ORDER BY NAME, PRODUCT_ID ASC)) AS RowNumber1, PRODUCT_ID
FROM PRODUCT
WHERE PRODUCT_ID in
(
SELECT PRODUCT_ID FROM PRODUCT
WHERE STATUS = 0
)
NH:
var middleCriteria = DetachedCriteria.For<TEntity>("TableWithRowNumber1Alias")
.SetProjection
(
Projections.ProjectionList()
.Add(
Projections.SqlProjection
(
"(ROW_NUMBER() OVER(ORDER BY NAME ASC, PRODUCT_ID ASC)) AS RowNumber1", /* The columns in after ORDER BY will be constructed dynamically later */
new string[] { "RowNumber1" },
new IType[] { NHibernateUtil.Int32 }
)
)
.Add(Projections.Property("Id").As("Id"))
)
.Add(Subqueries.PropertyIn("Id", innerCriteria));
3。 外部查询,它应该只返回一行,包含两列 - 行号和ID。
SQL:
SELECT TableWithRowNumber1Alias.RowNumber1 FROM PRODUCT
join (
SELECT (ROW_NUMBER() OVER(ORDER BY NAME, PRODUCT_ID ASC)) AS RowNumber1, PRODUCT_ID
FROM PRODUCT
WHERE PRODUCT_ID in
(
SELECT PRODUCT_ID FROM PRODUCT
WHERE STATUS = 0
)
) as TableWithRowNumber1Alias on TableWithRowNumber1Alias.PRODUCT_ID = PRODUCT.PRODUCT_ID
WHERE
TableWithRowNumber1Alias.PRODUCT_ID in (8) /* The ID passed from client */
NH:
var outerCriteria = (???).List();
如果我尝试从middleCriteria
获取结果(例如使用.List()),NHibernate会将它们提供给我。然后我可以在C#中迭代列表并获取我想要的数据,但这对于大型数据集来说效率不高。这就是为什么我需要帮助来实现'outerCriteria',这将限制SQL级别的数据。