【问题标题】:Upgraded to .NET Core 3.1 and receiving an error in a LINQ query related to using .FirstOrDefault()升级到 .NET Core 3.1 并在与使用 .FirstOrDefault() 相关的 LINQ 查询中收到错误
【发布时间】:2020-12-03 09:37:51
【问题描述】:

我有一个实体框架控制器,它已成功使用以下方法。但是,我最近更新了我的项目以使用 .NET Core 3.1,它一定有什么问题。

我现在收到此错误:

FirstOrDefault()' 无法翻译。以可翻译的形式重写查询,或通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用显式切换到客户端评估

我做了一些研究,有人说不要使用我在下面的查询中所做的GroupBy 扩展名。我试图将其取出,但这只会产生更多错误。

我也去了this

但我不知道如何修复下面的复杂查询。

老实说,我不确定它为什么会失败或如何正确修复它。

有没有人觉得有什么不对?

谢谢!

 public async Task<ActionResult<object>> GetStarChemicalData(string starID)
        {
            var starChemicalData = await (from starlist in _context.StarList
                                          join ql in _context.ChemicalList on starlist.ChemicalId equals ql.ChemicalId into stars
                                          from chemicallist in stars.DefaultIfEmpty()
                                          join qc in _context.ChemicalAtoms on chemicallist.ChemicalId equals qc.ChemicalId into chemicals
                                          from chemicalatoms in chemicals.DefaultIfEmpty()
                                          join nk in _context.StarLinks on chemicalatoms.AtomId equals nk.AtomId into links
                                          from starlinks in links.DefaultIfEmpty()
                                          where starlist.StarId == starID
                                          select new
                                          {
                                              StarId = starlist.StarId,
                                              StarType = starlist.StarType,
                                              StarTitle = starlist.StarTitle,
                                              ChemicalId = starlist.ChemicalId,
                                              AtomId = (Guid?)chemicalatoms.AtomId,
                                              OrderId = chemicalatoms.OrderId,
                                              ChemicalText = chemicallist.ChemicalText,
                                              AtomText = chemicalatoms.AtomText,
                                              Wavelength = chemicalatoms.Wavelength,
                                              isRedShifted = (starlinks.AtomId != null && starlist.StarType == 1) ? 1
                                              : (starlinks.AtomId == null && starlist.StarType == 1) ? 0
                                              : (int?)null
                                          })
                                              .GroupBy(x => x.StarId)
                                              .Select(g => new
                                              {
                                                  StarId = g.FirstOrDefault().StarId,
                                                  StarType = g.FirstOrDefault().StarType,
                                                  StarTitle = g.FirstOrDefault().StarTitle,
                                                  ChemicalId = g.FirstOrDefault().ChemicalId,
                                                  ChemicalText = g.FirstOrDefault().ChemicalText,
                                                  ChemicalAtoms = (g.FirstOrDefault().AtomId != null ? g.Select(x => new
                                                  {
                                                      AtomId = x.AtomId,
                                                      OrderId = x.OrderId,
                                                      AtomText = x.AtomText,
                                                      Feedback = x.Wavelength,
                                                      IsCorrect = x.isRedShifted
                                                  }) : null)
                                              }).FirstOrDefaultAsync();

            return starChemicalData;

调试后出错:

.Select(x => new { 
    AtomId = x.AtomId, 
    OrderId = x.OrderId, 
    AtomText = x.AtomText, 
    Feedback = x.Wavelength, 
    IsCorrect = x.isRedShifted
 })' could not be translated.

【问题讨论】:

  • 使用导航属性重写查询。然后很可能你会发现它不需要有问题的GroupBy。当前查询看起来很复杂,因为它使用转换为 LINQ 的 SQL 方法,而它应该是其他方式。查看当前查询,我希望得到一些简单的东西,例如 _context.StarList.Select(sl =&gt; new { sl.StarId/, * other sl properties ...*/, ChemicalAtoms = sl.ChemicalAtoms.Select(ca =&gt; new { ca.AtomId/, * other ca properties ...*/ }) })
  • 我查看了 Microsoft 文档,试图弄清楚导航属性是什么。那么它们只是不在数据库中的类吗?此外,我的 GroupBy 使用 id (StarId)。该 ID 在数据库中。所以我不太确定如何进行。
  • @IvanStoev 我花了一些时间尝试按照使用建议重写查询。但是 ChemicalAtoms 不是 StartList 的一部分。 ChemicalAtoms 来自一个连接。所以我不能按照你的建议做;即:sl.ChemicalAtoms.Select(...)

标签: entity-framework linq entity-framework-core iqueryable asp.net-core-3.1


【解决方案1】:

您有很多 FirstOrDefault (s) 调用。

要“安全”地对它们进行编码,您可以试试这个:

.FirstOrDefault() ?? string.Empty

.FirstOrDefault() ?? 0

.. 以上是这个的简写版本:(null check + ? 三元运算符)(同样,这是一种“安全”的编码方式)

StarId = null == g.FirstOrDefault() ? 0 : g.FirstOrDefault().StarId,
StarType = null == g.FirstOrDefault() ? string.Empty : g.FirstOrDefault().StarType,
StarTitle = null == g.FirstOrDefault() ? string.Empty : g.FirstOrDefault().StarTitle,

..

但最好调试一下,找出问题所在

将所有这些(临时性)更改为“”和 0

我列出了其中的 3 个,但您应该全部更改

而不是这个:

StarId = g.FirstOrDefault().StarId,
StarType = g.FirstOrDefault().StarType,
StarTitle = g.FirstOrDefault().StarTitle,

使用(暂时)这个:

   StarId = 0,
   StarType = "",
    StarTitle = "",

(再次做所有这些)

并一个接一个,替换回来

    StarId = g.FirstOrDefault().StarId,
   StarType = "",
    StarTitle = "",

找到“罪魁祸首”。

这里有一些伪代码......你可以尝试使用 IQueryable 的中间步骤。它的伪代码,你必须调整。

IQueryable 是一种“慢慢构建查询”而不是编写单个超级查询的方法......并且有助于调试。最终,您将注释掉(或删除)... tempDebuggingCollection ........ 但它可以帮助您到达您想去的地方。

public async Task<ActionResult<object>> GetStarChemicalData(string starID)
        {
            IQueryable<YourObjectHere> starChemicalDataQueryable = await (from starlist in _context.StarList
                                          join ql in _context.ChemicalList on starlist.ChemicalId equals ql.ChemicalId into stars
                                          from chemicallist in stars.DefaultIfEmpty()
                                          join qc in _context.ChemicalAtoms on chemicallist.ChemicalId equals qc.ChemicalId into chemicals
                                          from chemicalatoms in chemicals.DefaultIfEmpty()
                                          join nk in _context.StarLinks on chemicalatoms.AtomId equals nk.AtomId into links
                                          from starlinks in links.DefaultIfEmpty()
                                          where starlist.StarId == starID;
                                    
            ICollection<YourObjectHere> tempDebuggingCollection = starChemicalDataQueryable.ToListAsync(CancellationToken.None);
                                    
                    
            var starChemicalData = starChemicalDataQueryable
                                        select new
                                          {
                                              StarId = starlist.StarId,
                                              StarType = starlist.StarType,
                                              StarTitle = starlist.StarTitle,
                                              ChemicalId = starlist.ChemicalId,
                                              AtomId = (Guid?)chemicalatoms.AtomId,
                                              OrderId = chemicalatoms.OrderId,
                                              ChemicalText = chemicallist.ChemicalText,
                                              AtomText = chemicalatoms.AtomText,
                                              Wavelength = chemicalatoms.Wavelength,
                                              isRedShifted = (starlinks.AtomId != null && starlist.StarType == 1) ? 1
                                              : (starlinks.AtomId == null && starlist.StarType == 1) ? 0
                                              : (int?)null
                                          })
                                              .GroupBy(x => x.StarId)
                                              .Select(g => new
                                              {
                                                  StarId = g.FirstOrDefault().StarId,
                                                  StarType = g.FirstOrDefault().StarType,
                                                  StarTitle = g.FirstOrDefault().StarTitle,
                                                  ChemicalId = g.FirstOrDefault().ChemicalId,
                                                  ChemicalText = g.FirstOrDefault().ChemicalText,
                                                  ChemicalAtoms = (g.FirstOrDefault().AtomId != null ? g.Select(x => new
                                                  {
                                                      AtomId = x.AtomId,
                                                      OrderId = x.OrderId,
                                                      AtomText = x.AtomText,
                                                      Feedback = x.Wavelength,
                                                      IsCorrect = x.isRedShifted
                                                  }) : null)
                                              }).FirstOrDefaultAsync();                                       
  

            return starChemicalData;

............

再次,同样的安全检查:

               ChemicalAtoms = (g.FirstOrDefault().AtomId != null ? g.Select(x => new
                                              {
                                                  AtomId = x.AtomId,
                                                  OrderId = x.OrderId,
                                                  AtomText = x.AtomText,
                                                  Feedback = x.Wavelength,
                                                  IsCorrect = x.isRedShifted
                                              }) : null)

您没有安全地检查 g.FirstOrDefault() ....

类似这样的:

         ChemicalAtoms = null == g.FirstOrDefault() ? null : (g.FirstOrDefault().AtomId != null ? g.Select(x => new
                                              {
                                                  AtomId = x.AtomId,
                                                  OrderId = x.OrderId,
                                                  AtomText = x.AtomText,
                                                  Feedback = x.Wavelength,
                                                  IsCorrect = x.isRedShifted
                                              }) : null)

【讨论】:

  • 谢谢,所以您认为其中一个值设置不正确并导致错误?
  • 我认为.... FirstOrDefault 带回了一个空值,当您编码“g.FirstOrDefault().StarId”时......它~~假设~~它不是空值,并且属性调用 (.StarId) 失败并出现您收到的错误。如果你不做“安全”,那么你应该写这些 g.First().StarId, .. 这意味着你非常确定第一个存在。
  • 对这个答案印象深刻,只是在这里拍拍你的后背
  • 哇,谢谢...所以我确实添加了调试测试值并得到了一个不同的错误..我将其添加到上述问题的末尾。谢谢!
  • 显然这个答案来自一般的编程背景。实际问题虽然与安全性和空值没有任何共同之处 - 这些在 SQL 查询被成功翻译时自然处理,这种特殊类型的 LINQ 查询不会发生这种情况 - GrouBy 结果除了简单的键/聚合,如docs 中所述。
猜你喜欢
  • 1970-01-01
  • 2021-10-13
  • 2021-05-14
  • 1970-01-01
  • 2020-03-29
  • 2022-06-13
  • 1970-01-01
  • 2021-05-04
  • 2020-08-22
相关资源
最近更新 更多