Entity framework 使用let子句进行具有计算值的LINQ查询

Entity framework 使用let子句进行具有计算值的LINQ查询,entity-framework,linq,Entity Framework,Linq,我正在使用ASP.NET核心版本1.1和实体框架 我有一个数据库,其中有一个引擎表和一个引擎测试表。我试图得到最后的测试结果,并将其与每个发动机记录一起显示。我还想对测试结果进行计算 我想在控制器中执行以下操作,并在视图中显示结果: var engines = from engine in _context.Engine orderby engine.SerialNumber let lastTest = (

我正在使用ASP.NET核心版本1.1和实体框架

我有一个数据库,其中有一个引擎表和一个引擎测试表。我试图得到最后的测试结果,并将其与每个发动机记录一起显示。我还想对测试结果进行计算

我想在控制器中执行以下操作,并在视图中显示结果:

var engines = from engine in _context.Engine
              orderby engine.SerialNumber
              let lastTest =
                (from t in _context.Test
                 where t.EngineId == engine.EngineId
                 orderby t.TestDate descending
                 select t.TestValue)
                .FirstOrDefault()
              select new EngineVM
              {
                  EngineId = engine.EngineId,
                  Make = engine.Make,
                  Model = engine.Model,
                  SerialNumber = engine.SerialNumber,
                  Status = CalculateEngineStatus(engine.EngineId, engine.AllowedAmount, lastTest)
              };
我得到以下错误:

SqlException:如果子查询没有引入EXISTS,则只能在选择列表中指定一个表达式


我尝试了不同的方法来编写查询,但没有成功。如果您有任何建议,我们将不胜感激。

您已经编写了查询。无法在firstOrDefault之后选择from,因为它不返回集合。按以下步骤进行:

var engines = from engine in _context.Engine
orderby engine.SerialNumber
let lastTest =
(from t in _context.Test
 where t.EngineId == engine.EngineId
 orderby t.TestDate descending
select t.TestValue)
.FirstOrDefault();


 if(engines != null)
{
 // do your calculation here
}

不确定为什么会出现SqlException失败,但它看起来像是EF核心SQL转换器的问题(我在EF 6中没有这个问题)

尽管如此,以下等效查询仍然有效(通过外部联接)


注意:经过一番研究,使用SQL Server Profiler,EF Core似乎会将此转换为所有引擎和所有测试的两条
SELECT
语句。EF 6的SQL Translator执行一个查询,但EF Core的情况并非如此,它解决了内存中的问题。您可能应该重新设计这段代码,并想出一些EF Core认为更容易理解的东西

这显然是错误的方法,您必须使用导航属性并避免任何存在、连接等。您是否在模型中定义了外键关系?在visual studio中,我遇到了一个语法错误“查询正文必须以select子句或group子句结尾”
var lastTestQuery = from test in _context.Test
                    group test by test.EngineId into engineTests
                    select (from t in engineTests orderby t.TestDate descending select t).FirstOrDefault();

var engines = from engine in _context.Engine
            orderby engine.SerialNumber
            join lastTest in lastTestQuery on engine.EngineId equals lastTest.EngineId into lastEngineTest
            let lastEngineTestValue = (from t in lastEngineTest select t.TestValue).FirstOrDefault()
            select new EngineVM
            {
                EngineId = engine.EngineId,
                Make = engine.Make,
                Model = engine.Model,
                SerialNumber = engine.SerialNumber,
                Status = CalculateEngineStatus(engine.EngineId, engine.AllowedAmount, lastEngineTestValue)
            };