[英]SetMaxResult for query and subquery
I am trying to create complex query with paging using NHibernate. 我正在尝试使用NHibernate进行分页创建复杂的查询。 Something like this:
像这样:
SELECT TOP 10 * FROM (
SELECT
ROW_COUNT() ... as 'rowNum',
Value,
(SELECT TOP 1 FROM Table1 WHERE Condition ORDER BY Column)
FROM Table2
WHERE EXISTS(SELECT null FROM Table1 WHERE Condition)
) WHERE rowNum > 10
The simplest test-case to reproduce issue is: 重现问题的最简单的测试用例是:
var criteria = CurrentSession.CreateCriteria<Table>();
var subCriteria = DetachedCriteria.For<Table>()
.SetProjection(Projections.Id())
.SetMaxResults(1);
criteria.SetProjection(Projections.ProjectionList()
.Add(Projections.Constant(1))
.Add(Projections.SubQuery(subCriteria)))
.SetMaxResults(10)
.SetFirstResult(1)
.List();
Unfortunately, this produces wrong SQL - subqueries SetMaxResult screws all up. 不幸的是,这会产生错误的SQL-子查询SetMaxResult螺钉全部固定。 How can I fix it?
我该如何解决?
In order to overcome this bug I had to rewrite the dialect. 为了克服此错误,我不得不重写方言。 It might not be that good and clean but here it is.
它可能不是那么好干净,但是确实如此。 All the changes are inside this method:
所有更改都在此方法内部:
private static int GetFromIndex(SqlString querySqlString)
{
/* A large amount of modifications were made to the following code in order to work around the bug here: https://nhibernate.jira.com/browse/NH-3286*/
var queryRealString = querySqlString.ToString();
// Remove any 'TOP (?)' clauses from the query because 'GetSubselectString' doesn't handle them
var querySqlStringWithoutTops = new SqlString(queryRealString.Replace(" TOP (?)", ""));
string subselect = querySqlStringWithoutTops.GetSubselectString().ToString();
// Regex match the subselect - the original code got this part wrong too
int fromIndex = Regex.Match(querySqlStringWithoutTops.ToString(), Regex.Escape(subselect) + @"($|\s|\,|\)|\n)", RegexOptions.Multiline).Index;
// Not sure if the next bit is going to work with our changes...
if (fromIndex == -1)
{
fromIndex = queryRealString.ToLowerInvariant().IndexOf(subselect.ToLowerInvariant());
}
// Work out the length of all the 'TOP (?)' that were removed above
var currentStart = 0;
var lengthOfDeletedTops = 0;
int ixOfTops;
var topLength = " TOP (?)".Length;
while (currentStart < fromIndex
&& (ixOfTops = queryRealString.IndexOf(" TOP (?)", currentStart, fromIndex - currentStart, StringComparison.OrdinalIgnoreCase)) >= 0)
{
lengthOfDeletedTops += topLength;
currentStart = ixOfTops + topLength;
}
return fromIndex + lengthOfDeletedTops;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.