【问题标题】:Linq, lambda expression and OrderByLinq、lambda 表达式和 OrderBy
【发布时间】:2012-02-17 01:41:56
【问题描述】:

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

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 是字符串类型:

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

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

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

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

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

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

【问题讨论】:

  • 哪个属性是 DateTime 类型的?
  • 您的方法名称有些混乱。您实际上是在执行 Min/Max 函数,但重载了另一种方法的名称,该方法执行的操作完全不同。我会小心的。
  • @ArsenMkrt:我的所有模型都派生自一个基础模型,该基础模型具有 DateCreated 类型的 DateTime 属性。
  • @JeffMercado 你能详细说明一下吗?你说的听起来很有趣,但我不确定我还重载了哪些其他函数?
  • 当我看到FirstOrDefault() 方法时,我期望它返回集合中的第一项,或者如果它为空则返回类型的默认值。这是标准的 LINQ 方法。在这里,您定义了一个名称相似的方法,它做的事情完全不同,因此造成了混乱。该实现是通常用于在集合中查找最小值或最大值的项目的模式。我会将此方法命名为其他名称。一些这样做的库将其称为MinBy()MaxBy()。我建议将其命名为 MinMaxByOrDefault() 或类似的名称。

标签: linq lambda sql-order-by


【解决方案1】:

似乎这个方法是泛型类的一部分,这是类型参数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 中赋值 =,而是希望 ==。幸运的是,您的代码甚至无法编译。)

【讨论】:

  • 感谢您的详细解释!我以为我已经尝试过了,但它没有工作,但我一定做了一些不同的事情,因为现在它正在工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多