Linq,lambda表达式和OrderBy

时间:2012-02-16 16:09:16

标签: linq lambda sql-order-by

我的存储库中有这个通用方法:

public T GetFirstOrDefault(Expression<Func<T, bool>> where, Expression<Func<T, object>> keySelector, bool ascending)
{
    if (ascending)
    {
        return dbset.Where(where).OrderBy(keySelector).FirstOrDefault<T>();
    }
    else
    {
        return dbset.Where(where).OrderByDescending(keySelector).FirstOrDefault<T>();
    }
}

我希望能够像这样使用它,其中DateCreated的类型为DateTime:

someRepository.GetFirstOrDefault(m => m.myprop == someValue, m => m.DateCreated, true);

和这样,其中Id的类型为Int:

someRepository.GetFirstOrDefault(m => m.myprop == someValue, m => m.Id, true);

并且像这样,其中Name的类型为string:

someRepository.GetFirstOrDefault(m => m.myprop == someValue, m => m.Name, true)

但是,当我使用它时,它会给我以下错误:

无法将类型'System.DateTime'强制转换为'System.Object'。 LINQ to Entities仅支持转换实体数据模型基元类型。

在做了一些研究后,我发现可能我必须使用Expression<Func<TSource, TKey>>类型的keySelector或类似的东西,这就是我感到困惑的地方。如果我这样声明我的方法,我不确定TKey应该来自哪里:

public T GetFirstOrDefault(Expression<Func<T, bool>> where, Expression<Func<TSource, TKey>> keySelector, bool ascending) { }

我是在正确的道路上吗?我的OrderBy子句应该如何声明?

1 个答案:

答案 0 :(得分:3)

似乎这个方法是泛型类的一部分,它是类型参数T的来源。如果您只需要此方法的其他类型参数,则必须使该方法本身通用:

public T GetFirstOrDefault<TKey>(
    Expression<Func<T, bool>> where,
    Expression<Func<T, TKey>> keySelector,
    bool ascending)

然后您可以调用它并明确指定参数:

someRepository.GetFirstOrDefault<string>(m => m.myprop == someValue, m => m.Name, true)

或者让编译器推断它:

someRepository.GetFirstOrDefault(m => m.myprop == someValue, m => m.Name, true)

(注意你肯定不希望在第一个lambda中赋值=,你想要==。幸运的是,你的代码甚至都不会编译。)