升级到 .NET Core 3.1 并在与使用 .FirstOrDefault() 相关的 LINQ 查询中收到错误

Upgraded to .NET Core 3.1 and receiving an error in a LINQ query related to using .FirstOrDefault()

我有一个 Entity Framework 控制器成功地使用了下面的方法。但是,我最近更新了我的项目以使用 .NET Core 3.1,它一定有问题。

我现在收到这个错误:

FirstOrDefault()' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or 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.

您有很多 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 = "",

(再次全部完成)

和one-by-one,将它们替换回去

    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;

.......

AGain,同样的安全检查:

               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)