【问题标题】:Problems recreating LINQ query from SQL script从 SQL 脚本重新创建 LINQ 查询的问题
【发布时间】:2019-06-15 11:47:41
【问题描述】:

我正在努力将 SQL 查询“转换”为 LINQ 查询。我的 SQL 查询如下所示:

SELECT S.SummonerName, LE.LeaguePoints, LS.DateTime, SUM(LE.LeaguePoints)
FROM LadderEntries LE
JOIN Sumonners S on LE.SummonerId = S.Id
JOIN LadderSnapshots LS on LE.LadderSnapshotId = LS.Id
WHERE LS.Region = 'euw1'
AND DateTime = '2019-06-14 00:00:00'
OR DateTime = '2019-06-13 00:00:00'
and LS.Region = 'euw1'
GROUP BY S.SummonerName

这个查询给了我想要的结果。但是,到目前为止,我得到了以下 LINQ 查询:

from LE in _database.LadderEntries
join S in _database.Sumonners on LE.SummonerId equals S.Id
join LS in _database.LadderSnapshots on LE.LadderSnapshot.Id equals LS.Id
where LS.Region == param.Region && (LS.DateTime == param.Date || LS.DateTime == param.Date.AddDays(-1))
group new {LE, S, LS} by S.SummonerName
into C
select new GetLadderEntryDifferencesEntry
{
    LpDifference = C.Select(a => a.LE.LeaguePoints).Sum(),
    SummonerName = C.Select(a => a.S.SummonerName).FirstOrDefault()
};

但这给了我执行时的错误InvalidOperationException: Error generated for warning 'Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning: The LINQ expression 'GroupBy([S].SummonerName, new <>f__AnonymousType5'3(LE = [LE], S = [S], LS = [LS]))' could not be translated and will be evaluated locally.'.

我想知道我做错了什么。

注意:我正在使用 sqllite 和 ef 核心,如果这有影响的话。

【问题讨论】:

  • EF 核心真的很棘手,你会对你不能做的事情感到惊讶,首先购买将 FirstOrDefault 更改为 C.Key 并更改,然后你的 sql 会进行求和,并且该行会进行某种聚合,所以如果这是意图,请将其更改为.C.Sum(a=>a.LeaguePoints)。
  • 这些查询在功能上是不同的(返回不同的结果)——SQL 求和而 LINQ 不同?
  • @IvanStoev 我改变了它。我在弄乱代码,忘记改回来了。
  • @FilipCordas 我将选择对象更改为{ LpDifference = C.Sum(a => a.LE.LeaguePoints), SummonerName = C.Key },但是这给了我同样的错误
  • 对此我感到很惊讶,但 EF Core 真的很糟糕,对于 loooooong time 来说是个问题,也许 new {LE, S, LS} 尝试将其更改为 new {S.SummonerName, LE.LeaguePoints} 并在 @987654328 上进行汇总@ 和相同的 Key select 也可以尝试将其从 new GetLadderEntryDifferencesEntry{... 更改为 new {....

标签: c# sql entity-framework linq entity-framework-core


【解决方案1】:

我认为问题在于:

&& (LS.DateTime == param.Date || LS.DateTime == param.Date.AddDays(-1))

试试这个:

var firstDate = param.Date;
var secondDate = param.Date.AddDays(-1);

然后

&& (LS.DateTime == firstDate || LS.DateTime == secondDate)

它可能会例外: SummonerName = C.Select(a => a.S.SummonerName).FirstOrDefault() 或如何安排分组。

这些实体是否设置了引用,表达式可以简化吗?

var ladderEntryDifferences = _database.LadderSnapshots
    .Where(x =>x.Region = param.Region 
        && (x => x.DateTime == firstDate || x.DateTime == secondDate)
    .GroupBy(x => x.LadderEntry.Summoner.SummonerName)
    .Select( g => new GetLadderEntryDifferencesEntry
    {
        LpDifference = g.Sum(x => x.LeagueEntry.LeaguePoints),
        SummonerName = g.Key // This will be the SummonerName
    }).ToList();

以上是对结构的猜测,并从记忆中拉出组,但它可能会给你一些尝试的想法。如果您的上下文没有在顶层公开 LadderSnapshots,那么您也应该能够从 LadderEntry 级别对其进行组合...

【讨论】:

    【解决方案2】:

    好的,这是我得到的,首先

    LS.Region = 'euw1'
    AND DateTime = '2019-06-14 00:00:00'
    OR DateTime = '2019-06-13 00:00:00'
    and LS.Region = 'euw1'
    

    和下面的linq不一样,sql中缺少参数。

    && (LS.DateTime == param.Date || LS.DateTime == param.Date.AddDays(-1))
    

    现在关于 group by 你可以尝试这样做

    from LE in _database.LadderEntries
    join S in _database.Sumonners on LE.SummonerId equals S.Id
    join LS in _database.LadderSnapshots on LE.LadderSnapshot.Id equals LS.Id
    where LS.Region == param.Region && (LS.DateTime == param.Date || LS.DateTime == param.Date.AddDays(-1))
    group LE by new {LE.SummonerName, S.SummonerName, LS.SummonerName} 
    into C
    select new GetLadderEntryDifferencesEntry
    {
        LpDifference = C.Select(a => a.LE.LeaguePoints).Sum(),
        SummonerName = C.Select(a => a.S.SummonerName).FirstOrDefault()
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2011-04-03
      • 2017-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-21
      相关资源
      最近更新 更多