2015-10-02 43 views
7

我有这个项目,我需要做的任务之一是查找特定对象出现在哪个页面上。该对象具有预定义的ID,并且该ID按从0到N的顺序出现,但它们可能会跳过值。计算在具有特定ID的项目之前出现多少项目

这意味着,显然,使用我正在寻找的元素的ID将不起作用,就好像它是25,并且每页应该有10个项目,但其中8项缺失,它会尝试以适应3页,但也只适合网页2.

这是我现在,我不知道是否有更好的方法:

int itemsPerPage = Convert.ToInt32(masterDbContext.Settings.First(x => x.Name == "ItemsPerPage").Value); 
int itemCount = masterDbContext.Items.OrderBy(x => x.Id).TakeWhile(x => x.Id < currentItemId).Count(); 
int pageNumber = (int)Math.Ceiling((double)itemCount/itemsPerPage); 

Response.Redirect("~/View/" + rootItem.Id + (pageNumber > 1 ? "/Page/" + pageNumber : "")); 

如果没有更好的办法做到这一点,没关系。我只是希望有,因为我敢肯定,TakeWhile可以采取,一段时间,当我有数以千计的Items在数据库中。

请注意:此方法目前的工作似乎。

+1

为什么你需要'GroupBy'在这里?不会'masterDbContext.Items.Count(x => x.Id ieaglle

+0

@ieaglle完美的工作! –

+0

我几乎可以肯定的是,两个版本都产生完全相同的SQL代码。所以这只是一个代码可读性优化,而不是性能。 – ieaglle

回答

4

你几乎有它。既然你是通过ID订购的物品,并用ID比具有计数有多少人少,你可以使用条件Count

var itemsPerPage = Convert.ToInt32(masterDbContext.Settings.First(x => x.Name == "ItemsPerPage").Value); 
var itemCount = masterDbContext.Items.Count(x => x.Id < currentItemId); 

人们也为TakeWhile LINQ扩展方法没有直接的SQL匹配。所以,你不使用它,当你希望你的LINQ查询转换为SQL

+0

这工作完美! (除了我偶然遗漏的一个条件,但那不是你的错。)我欣赏关于'TakeWhile'的失败的解释。我从来没有意识到它不适用于SQL。 (虽然它是有道理的,但我从来没有见过使用'TakeWhile'或任何可能看起来像它的东西的SQL查询。)我猜计数工作的踢球者是id始终按顺序排列,虽然它们可能跳过值仍然从低到高(总是)。 –

+0

@EBrown很高兴帮助! – vittore

+0

TakeWhile必须用游标实现:-) –

-3

尝试像

int itemCount = masterDbContext.Items.FindIndex(x => (x.Id == given_ID)); 
+1

请阅读这个问题:“但他们可能会跳过价值。” – Heslacher

+0

搜索与指定的谓词所定义的条件相匹配的元素,并返回整个列表中第一个匹配项的从零开始的索引。 (https://msdn.microsoft.com/en-us/library/x1xzf2ca(v=vs.110).aspx)所以你会得到不是25,但25-8(实际上16位零基础) –

+0

为什么你认为它是一个'List '? – Heslacher

2

假设这个使用某种形式的SQL提供的,所有你需要做的是类似于在SQL中的更好:

SELECT COUNT([Id]) 
FROM [Items] 
WHERE [Id] < @currentItemId 

C#LINQ:

masterDbContext.Items.Count(item => item.Id < currentItemId);