2015-04-21 4 views
3

Эй, что за гангстеры?Получение следующего и предыдущего на Queryable

У меня есть следующий код, который, как представляется, всегда возвращается null.

public static T GetNext<T>(this IQueryable<T> list, T current) 
    { 
     try 
     { 
      return list.SkipWhile(x => !x.Equals(current)).Skip(1).First(); 
     } 
     catch 
     { 
      return default(T); 
     } 
    } 

    public static T GetPrevious<T>(this IQueryable<T> list, T current) 
    { 
     try 
     { 
      return list.TakeWhile(x => !x.Equals(current)).Last(); 
     } 
     catch 
     { 
      return default(T); 
     } 
    } 

Учитывая запрашиваемый из источника данных и запись в него, я просто хочу, чтобы получить следующие и предыдущие значения.

+1

У вас Пробовал с '! ='? Я думаю, что это могло бы сделать ссылочное равенство. – Sayse

+0

Вы можете добавить индексирование в класс T и получить следующий и предыдущий объект по индексу. Вы можете проверить это http://stackoverflow.com/questions/1869304/determine-the-position-of-an-element-in-an-iqueryable – Peyman

+0

, это прекрасно работает на массиве ints ... – stefankmitph

ответ

4

Причина в том, что SkipWhile не поддерживается EntityFramework.

Во-первых, чтобы использовать Skip или Take, сборник должен быть некоторым, чтобы EntityFramework поддерживал эти методы. Таким образом, перед вызовом метода, вам необходимо иметь OrderBy метод:

var orderedList = list.OrderBy(elem => elem.Id) // or other property 
               // but need to be rememebered 
               // because it will be used in furher 

Тогда ваш метод следующий может быть STH так:

public static T GetNext<SomeEntity>(
      this IOrderedQueryable<SomeEntity> list, 
      SomeEntity current) 
{ 
    return list.Where(elem => elem.Id > current.Id) 
       .FirstOrDefault(); // faster than try-catch 
    // assuming, that Id is unique 
} 

Этот метод имеет один недостаток. Это не общий. Но с небольшим усилием, вы можете подготовить общую версию:

public static T GetNext<T>(this IOrderedQueryable<T> list, T current, string orderProperty) 
{ 
    var predicate = string.Format("{0} > @0", orderProperty); 
    var propValue = current.GetType() 
          .GetProperty(orderProperty, 
             BindingFlags.Public | BindingFlags.Instance) 
          .GetValue(current); 
    return (T)list.Where(predicate, propValue).FirstOrDefault(); 
        //where comes from System.Linq.Dynamic 
} 

Если вам не нравятся строки в качестве имен объектов недвижимости:

public static T GetNext<T>(this IOrderedQueryable<T> list, 
          T current, 
          Func<T, object> orderProperty) 
{ 
    .. 
    var propValue = orderProperty(current); 
    .. 
} 

и использования:

orderedList.GetNext(current, orderProperty: elem => elem.Id); 

Родового версии на System.Linq.Dynamic, которые находятся на codeplex

Надеюсь, это даст вам некоторое представление о том, как заставить ваш код работать или какую-то идею, как реализовать его с помощью другого подхода.

1

Может быть, я буду получать распят за это решение (потому что я считаю его вид грязный) ... но ... это работает (и не использует TakeWhile или SkipWhile или DynamicLINQ):

public static T GetNext<T>(this IQueryable<T> list, T current) 
{ 
    try 
    { 
     int idx = 0; 
     foreach (T item in list) 
     { 
      if (!item.Equals(current)) 
      { 
       idx++; 
      } 
      else 
      { 
       break; 
      } 
     } 

     return list.Skip(idx).First(); 
    } 
    catch 
    { 
     return default(T); 
    } 
} 

public static T GetPrevious<T>(this IQueryable<T> list, T current) 
{ 
    try 
    { 
     int idx = 0; 
     foreach (T item in list) 
     { 
      if (!item.Equals(current)) 
      { 
       idx++; 
      } 
      else 
      { 
       break; 
      } 
     } 
     if (idx - 1 == 0) 
      return list.First(); 
     return list.Skip(idx - 1).First(); 
    } 
    catch 
    { 
     return default(T); 
    } 
} 
+0

Я буду стрелять в везде, где я вижу u для написания этого кода – DarthVader

+0

@DarthVader я сказал: cruzified ... не выстрелил. это было бы несправедливо. – stefankmitph

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