对于这个相当复杂的逻辑,我需要什么LINQ?

时间:2013-11-19 00:25:35

标签: linq linq-to-sql composite-key

我正在查询的数据:

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

...具有“复合键”vals(ID + PackSize),例如:

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

IOW,ID不是唯一的;但ID和PackSize的组合是。如果我不必考虑一批记录在相同ID但不同包大小之间的“破解”结束/开始的可能性,我可以使用这个相对简单的LINQ语句:

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

...但由于逻辑不仅仅是“从下一个ID号开始获取下一批记录”,而是“开始从下一个ID号中取出下一批记录,除非有另一条记录相同的ID,但不同的PackSize“,我必须做一些棘手的事情。但是什么?如何在LINQ中表达这样的查询?

我试过这个:

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

......但它无休止地循环。现在我意识到第一个“where”需要考虑ID val可能与最后一个读取相同 - 前提是PackSize与前一个读取不同。无论是一天的晚些时候还是其他什么,我的脑袋即将破灭,试图解开这个难题。

更新

结合user1429080的答案(“.ToList()”在铂金中是值得的),我想我可以使用这个查询(他的两个建议的混合,因为ID是一个字符串,但PackSize是一个int):< / p>

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();

更新2

由于某种原因,它仍然无休止地循环,但......(甚至不是星期一)。

更新3

将lastPackSizeFetched的初始值从0更改为1解决了我的问题 - 瞧!

1 个答案:

答案 0 :(得分:1)

假设有问题的列实际上是数据库中的字符串,这应该可以帮助您:

//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();

请注意,如果列确实是字符串,那么结果的排序将是“怪异的”,因为“10”在“2”之前排序,依此类推。

另一方面,如果列是(正)整数(看起来像它们),你可以使用它:

//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();