I have a reasonably large set of phone numbers (approximately 2 million) in a database table. These numbers have been inserted in blocks, so there are many continuous ranges
SQL can't really do this in a single query (except there are native SQL enhancements I don't know about), because SQL can't access the row 'before' or 'after'.
You need to go through the sequence in a loop.
You may try NHibernates Enumerable, which doesn't load the entities into memory, but only creates proxies of them. Actually I don't think that it is a good idea, because it will create proxies for the whole 2 million numbers.
Plan B, use paging. Roughly, it looks like this:
List result = new List();
int input = 1012;
int pageSize = 100;
int currentPage = 0;
int expectedNumber = input;
bool carryOn = true;
while(carryOn)
{
var numbers = session
.CreateQuery("from PhoneNumber pn where pn.Number > :input")
.SetInt("input", input)
.SetFirstResult(currentPage * pageSize)
.SetMaxResult(pageSize)
.List();
foreach(var number in numbers)
{
expectNumber++;
if (number.Number != expectedNumber)
{
carryOn = false;
break;
}
result.Add(number);
}
currentPage++;
}
And the same for the range before in the other direction.