我有以下代码似乎总是返回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);
}
}
给定来自数据源的Queryable及其中的记录,我只想获取下一个和之前的值。
答案 0 :(得分:4)
原因是EntityFramework不支持SkipWhile
。
首先,要使用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
然后你的下一个方法可能是这样的:
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);
可在codeplex
上找到 System.Linq.Dynamic 的通用版本继电器我希望它能为您提供一些线索,让您了解如何使您的代码工作,或者知道如何使用其他方法实现它。
答案 1 :(得分: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);
}
}