通过dbset迭代得到下n行

时间:2014-02-07 07:12:00

标签: c# asp.net-mvc linq entity-framework

我试图找出在各种函数调用中不断迭代dbset的好方法,最后循环一次。

基本上我在数据库中有很多广告,我想在dbset.Ads上获取下一个(计数)

这是一个例子

ID   Text   Other Columns...
1    Ad1    ...
2    Ad2    ...
3    Ad3    ...
4    Ad4    ...
5    Ad5    ...
6    Ad6    ...

让我们说在我的视图中,我确定我需要为用户1显示2个广告。我想要返回广告1-2。用户2然后请求3个广告。我希望它返回3-5。用户3需要2个广告,该功能应该返回广告6和1,循环回到开头。

这是我一直在使用的代码(它在class AdsManager中):

Ad NextAd = db.Ads.First();
public IEnumerable<Ad> getAds(count)
{
    var output = new List<Ad>();
    IEnumerable<Ad> Ads = db.Ads.OrderBy(x=>x.Id).SkipWhile(x=>x.Id != NextAd.Id);
    output.AddRange(Ads);

    //If we're at the end, handle that case
    if(output.Count != count)
    {
        NextAd = db.Ads.First();
        output.AddRange(getAds(count - output.Count));
    }
    NextAd = output[count-1];

    return output;
}

问题是函数调用IEnumerable<Ad> Ads = db.Ads.OrderBy(x=>x.Id).SkipWhile(x=>x.Id != NextAd.Id);会在AddRange(Ads)上引发错误:

LINQ to Entities无法识别方法'System.Linq.IQueryable'1 [Domain.Entities.Ad] SkipWhile [Ad](System.Linq.IQueryable'1 [Domain.Entities.Ad],System.Linq。 Expressions.Expression'1 [System.Func`2 [Domain.Entities.Ad,System.Boolean]])'方法,并且此方法无法转换为商店表达式。

我最初将整个dbset加载到一个Queue中,并且确实入队/出队,但是当对数据库进行更改时,这不会更新。我根据Get the next and previous sql row by Id and Name, EF?

得出了这个算法的想法

我应该对数据库进行什么调用以获得我想要的内容?

更新:这是工作代码:

public IEnumerable<Ad> getAds(int count)
    {
        List<Ad> output = new List<Ad>();

        output.AddRange(db.Ads.OrderBy(x => x.Id).Where(x => x.Id >= NextAd.Id).Take(count + 1));

        if(output.Count != count+1)
        {
            NextAd = db.Ads.First();
            output.AddRange(db.Ads.OrderBy(x => x.Id).Where(x => x.Id >= NextAd.Id).Take(count - output.Count+1));
        }

        NextAd = output[count];
        output.RemoveAt(count);

        return output;
    }

2 个答案:

答案 0 :(得分:0)

EF不支持

SkipWhile;它无法转换为SQL代码。 EF基本上适用于集合而不是序列(我希望句子有意义)。

解决方法是简单地使用Where,例如:

IEnumerable<Ad> Ads = db.Ads.OrderBy(x=>x.Id).Where(x=>x.Id >= NextAd.Id);

答案 1 :(得分:0)

也许你可以将其简化为:

Ad NextAd = db.Ads.First();

public IQueryable<Ad> getAds(count)
{
    var firstTake = db.Ads
        .OrderBy(x => x.Id)
        .Where(x => x.Id >= NextAd.Id);

    var secondTake = db.Ads
        .OrderBy(x => x.Id)
        .Take(count - result.Count());

    var result = firstTake.Concat(secondTake);

    NextAd = result.LastOrDefault()

    return result;
}

抱歉,尚未对此进行测试,但它应该可以正常工作。