2014-02-07 6 views
0

Я пытаюсь выяснить, что является хорошим способом непрерывной итерации через dbset по различным вызовам функций, цикл один раз в конце.Перейдите через dbset, чтобы получить следующие n строк.

По сути я получил кучу объявлений в базе данных, и я хочу GetNext (COUNT) на dbset.Ads

Вот пример

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

Скажем, на мой взгляд, , Я определяю, что мне нужно 2 объявления для отображения для пользователя 1. Я хочу вернуть Объявления 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 для лиц, не узнайте метод «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 в очередь и сделал enqueue/dequeue, но это не будет обновляться, когда в базу данных были внесены изменения. Я получил идею для этого алгоритма на основе Get the next and previous sql row by Id and Name, EF?

Какой звонок я должен делать в базе данных, чтобы получить то, что я хочу?

UPDATE: Вот рабочий код:

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; 
    } 

ответ

0

SkipWhile не поддерживается в EF; он не может быть переведен в код SQL. EF в основном работает над наборами, а не последовательностями (я надеюсь, что предложение имеет смысл).

Обходной просто использовать Where, например:

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

Я могу оценить простоту. Итак, чтобы включить 'count', я просто использую' Take() ', как я это делал в' if' statement – CrazyTegger

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; 
} 

К сожалению, не проверял это, но он должен работать ,

Смежные вопросы