我刚刚升级到EF 3,我曾经使用过的查询之一现在给出了例外情况
ProductionRecords = _context.ProductionRecords
.Where(r => r.DataCriacao.Date == DateTime.Now.Date)
.Select(pr => new ProductionRecordViewModel
{
Id = pr.Id,
Operador = pr.Operador,
DataCriacao = pr.DataCriacao,
Celula = pr.Celula.Name,
Turno = pr.Turno.Name,
TotalPecasSemDefeito = pr.ReferenceRecords.Sum(c => c.Quantity),
TotalPecasComDefeito = pr.DefectRecords.Sum(c => c.Quantidade),
TotalTempoParado = pr.StopRecords.Sum(c => Convert.ToInt32(c.Duration.TotalMinutes)),
})
.AsNoTracking()
.ToList();
当我尝试将集合与时间跨度和持续时间相加时,会发生异常。...
我现在应该如何处理?
这是个例外
InvalidOperationException:LINQ表达式 '(EntityShaperExpression:EntityType:StopRecord ValueBufferExpression:(ProjectionBindingExpression: EmptyProjectionMember)IsNullable:False).Duration.TotalMinutes' 无法翻译。可以使用以下形式重写查询: 进行翻译,或通过插入来明确切换到客户评估 调用AsEnumerable(),AsAsyncEnumerable(),ToList()或 ToListAsync()。有关详情,请参见https://go.microsoft.com/fwlink/?linkid=2101038 更多信息。
答案 0 :(得分:3)
与其尝试教EF Core如何计算时间跨度,不如向数据库添加计算列吗?
public TimeSpan Duration { get; set; }
public int Minutes { get; }
entity.Property(e => e.Minutes)
.HasComputedColumnSql("DATEDIFF(MINUTE, 0, Duration)");
答案 1 :(得分:2)
EF3中发生了重大变化,除非在查询链的最末端(您的Convert.ToInt32(c.Duration.TotalMinutes)
可能依赖),否则EF3不会自动恢复为客户端评估。
尝试像这样重写查询:
ProductionRecords = _context.ProductionRecords
.Where(r => r.DataCriacao.Date == DateTime.Now.Date)
.AsNoTracking()
.AsEnumerable()
.Select(pr => new ProductionRecordViewModel
{
Id = pr.Id,
Operador = pr.Operador,
DataCriacao = pr.DataCriacao,
Celula = pr.Celula.Name,
Turno = pr.Turno.Name,
TotalPecasSemDefeito = pr.ReferenceRecords.Sum(c => c.Quantity),
TotalPecasComDefeito = pr.DefectRecords.Sum(c => c.Quantidade),
TotalTempoParado = pr.StopRecords pr.StopRecords.Sum(c => Convert.ToInt32(c.Duration.TotalMinutes)),
})
.ToList();
UPD 正如评论中已正确指出的那样-这基本上会将.Select
评估推迟到客户端。这可能会导致性能问题。此行为很可能是首先对EF Core 3进行了此更改的原因。
我没有足够的细节向您推荐合适的解决方案,但是似乎您无法摆脱对所有结果加载StopRecords
的麻烦。编写自定义方法转换器可以为您提供帮助。有关如何操作的信息,请参见我的other answer。我迅速检查了EF Core 3的来源,看来IMethodCallTranslator仍然存在。这意味着您很有可能建立一个自定义函数,该函数将在SQL中将日期转换为TotalMinutes。