Question

The data I'm querying like so:

SELECT id, pack_size, . . ., duckbillFactor FROM platypus ORDER BY id, pack_size

...has "composite key" vals (ID + PackSize) such as:

ID  PackSize
==  ========
123 1
124 1
125 1
125 6
126 1
. . .

IOW, IDs are not unique; but the combination of ID and PackSize are. If I didn't have to consider the possibility that a batch of records end/begin on the "crack" between the same ID but different pack size, I could use this relatively simple LINQ statement:

return inventoryItems.Where(i => 0 < String.Compare(i.Id, ID)).Take(CountToFetch);

...but since the logic is not simply "start fetching the next batch of records from the next ID number" but rather, "start fetching the next batch of records from the next ID number, unless there is another record with the same ID but a different PackSize", I've got to do something trickier. But what? How can I express such a query in LINQ?

I had tried this:

return inventoryItems.Where(i => 0 < String.Compare(i.Id, ID)).Where(i => 0 < String.Compare(i.PackSize.ToString(), packSize)).Take(CountToFetch);

...but it loops endlessly. And now I realize that the first "where" needs to consider that the ID val could be the same as the last one read - provided the PackSize is NOT the same as the previous one read. Whether it's the late hour of the day or something else, my head is about to bust trying to unravel this conundrum.

UPDATE

Combining user1429080's answer (the ".ToList()" is worth its weight in platinum), I think I can use this query (a mixture of his two suggestions because ID is a string, but PackSize is an int):

return inventoryItems
    .Where(i => (i.Id.CompareTo(ID) == 0 && i.PackSize > packSize) || i.Id.CompareTo(ID) > 0)
    .OrderBy(i => i.Id)
    .ThenBy(i => i.PackSize)
    .Take(CountToFetch)
    .ToList();

UPDATE 2

It's still endlessly looping for some reason, though... (and it's not even Monday).

UPDATE 3

Changing the initial value of lastPackSizeFetched from 0 to 1 solved my problem - voila!

Was it helpful?

Solution

Assuming that the columns in question are actually strings in the database, this should get you on the way:

//get first page
string firstRecordId = "";
string firstRecordPs = "";
int pageSize = 4;
var page1 = ctx.inventoryItems
    .Where(i =>
        (i.ID.CompareTo(firstRecordId) == 0 && i.PackSize.CompareTo(firstRecordPs) > 0)
        || i.ID.CompareTo(firstRecordId) > 0)
    .OrderBy(i => i.ID)
    .ThenBy(i => i.PackSize)
    .Take(pageSize)
    .ToList();

//get next page
firstRecordId = page1[page1.Count - 1].ID;
firstRecordPs = page1[page1.Count - 1].PackSize;
var page2 = ctx.inventoryItems
    .Where(i =>
        (i.ID.CompareTo(firstRecordId) == 0 && i.PackSize.CompareTo(firstRecordPs) > 0)
        || i.ID.CompareTo(firstRecordId) > 0)
    .OrderBy(i => i.ID)
    .ThenBy(i => i.PackSize)
    .Take(pageSize)
    .ToList();

Note that if the columns are indeed strings, then the ordering of the result will be "weird", since "10" sorts before "2" and so on.

If on the other hand the columns are (positive) integers (which it seems like they are), you can use this:

//get first page
int firstRecordId = 0;
int firstRecordPs = 0;
int pageSize = 4;
var page1 = ctx.inventoryItems
    .Where(i => (i.ID == firstRecordId && i.PackSize > firstRecordPs)
        || i.ID > firstRecordId)
    .OrderBy(i => i.ID)
    .ThenBy(i => i.PackSize)
    .Take(pageSize)
    .ToList();

//get next page
firstRecordId = page1[page1.Count - 1].ID;
firstRecordPs = page1[page1.Count - 1].PackSize;

var page2 = ctx.inventoryItems
    .Where(i => (i.ID == firstRecordId && i.PackSize > firstRecordPs)
        || i.ID > firstRecordId)
    .OrderBy(i => i.ID)
    .ThenBy(i => i.PackSize)
    .Take(pageSize)
    .ToList();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top