【问题标题】:A LINQ extension that I wrote will not work with Entity Framework我编写的 LINQ 扩展不适用于实体框架
【发布时间】:2011-07-18 14:00:44
【问题描述】:

我有一个这样定义的扩展方法:

public static TSource MaxBy<TSource, TResult>(this IEnumerable<TSource> collection, Func<TSource, TResult> func) where TSource : class
{
    var comparer = Comparer<TSource>.Default;
    TSource maxItem = null;
    foreach (var item in collection)
    {
        if (comparer.Compare(item, maxItem) > 0)
            maxItem = item;
    }
    return maxItem;
}

然后我在以下 LINQ-to-Entities 查询中使用它:

var balancesQuery = from t in db.Transactions
                    where t.UserId == userId
                    group t by t.CurrencyCode into tg
                    let tMaxDate = tg.MaxBy(i => i.TsCreate)
                    join c in db.Currencies on tg.Key equals c.CurrencyCode
                    select new { Currency = c, Balance = tMaxDate.Balance }

所以我要做的是 - 获取每种货币(按 CurrencyCode 分组)的最新交易 (MaxBy TsCreate),然后针对每笔交易选择余额。

我的问题是 - 这不适用于实体框架(LINQ-to-Entities;我得到:

LINQ to Entities 无法识别方法 'Transaction MaxBy[Transaction,DateTime](System.Collections.Generic.IEnumerable'[Transaction], System.Func'2[Transaction,System.DateTime])' 方法,并且这个方法不能翻译成商店表达式。

同样的查询也适用于 LINQ to SQL。

我的问题是:

  1. 有没有办法让它与实体框架一起工作?
  2. 或者也许有更好的方法来查询相同的信息,这适用于实体框架?

提前感谢您的帮助!

【问题讨论】:

    标签: entity-framework linq-to-sql linq-to-entities


    【解决方案1】:

    查询是否与:

    var balancesQuery = from t in db.Transactions
                        where t.UserId == userId
                        group t by t.CurrencyCode into tg
                        join c in db.Currencies on tg.Key equals c.CurrencyCode
                        select new { 
                            Currency = c, 
                            Balance = tg.OrderByDescending(i => i.TsCreate).Take(1).Balance 
                        };
    

    【讨论】:

    • 确实,这就是我要找的...谢谢!我只是想知道 - 是否可以编写 LINQ-to-Entities 查询,以便使用 GROUP BY CurrencyCode HAVING MAX(TsCreate) 生成 SQL 查询?因为 subselect 查询没问题,但效率不高(对于少数货币当然没关系)
    • 我认为在 linq 中它仍然会导致子查询,因为没有 having - 如果您在分组数据上使用 where 可能会创建。
    • 我认为Take(1) 必须是FirstOrDefault?正如Take 返回一个序列而不是一个元素。
    【解决方案2】:

    您不能对实际从数据库中提取数据的 LINQ 查询使用扩展,因为它不可能转换为 SQL。但是,您可以通过使用ToArray()ToList() 将结果返回到内存中来触发数据库查询执行,然后对内存中生成的真实数据调用扩展函数。

    【讨论】:

      猜你喜欢
      • 2021-11-05
      • 2016-07-29
      • 1970-01-01
      • 2017-08-01
      • 2021-07-09
      • 2015-11-12
      • 2011-06-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多