c# - LINQ GroupBy 生成不完整的查询
问题描述
我有一个非常简单的 LINQ 用例,现在我已经坚持了好几个小时。以下代码在列表中返回一个列表(1 个没有名称的组元素)。为什么它不能在 SQL 中正确翻译?我使用 EF Core 2.2。
我的 TileDetail 模型类:
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
namespace FAST_API.Models
{
public class TileDetailsContext : DbContext
{
public TileDetailsContext(DbContextOptions<TileDetailsContext> options)
: base(options)
{
}
public DbQuery<TileDetail> TileDetailsItems{ get;set; }
}
[Table("WFD_MOTOR_EVENTS_AUFTRAEGE", Schema = "SF")]
public class TileDetail
{
public string AUFTRAG { get; set; }
public string PMPS { get; set; }
public string ESN { get; set; }
public string AUFTRAGSBEZ { get; set; }
public int VORGANGSNR { get; set; }
public string VORGANGSTEXT { get; set; }
public char AUFTRAG_FERTIG { get; set;}
public double? IST_BEGINN { get; set; }
public double? IST_ENDE { get; set; }
public DateTime? AG_IST_BEGINN {
get { return (IST_BEGINN == null ? (DateTime?)null: new DateTime(1970,1,1).AddDays(Convert.ToDouble(IST_BEGINN))); }
}
public DateTime? AG_IST_ENDE {
get { return (IST_ENDE == null ? (DateTime?)null: new DateTime(1970,1,1).AddDays(Convert.ToDouble(IST_ENDE))); }
}
public char VORGANG_FERTIG { get; set; }
public bool AUFTRAG_FERTIG_STATUS {
get { return AUFTRAG_FERTIG != 'J' ? true: false; }
}
public bool VORGANG_FERTIG_STATUS {
get { return VORGANG_FERTIG != 'J' ? true: false; }
}
}
}
这是我使用 LINQ 的控制器:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using FAST_API.Models;
namespace FAST_API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TileDetailsController : ControllerBase
{
private readonly TileDetailsContext _context;
public TileDetailsController(TileDetailsContext context)
{
_context = context;
}
// GET: api/TileDetails
[HttpGet]
public IEnumerable<TileDetail> GetTileDetailsItems()
{
return _context.TileDetailsItems.ToList();
}
// GET: api/TileDetails/706722
[HttpGet("{id}")]
public async Task<IActionResult> GetTileDetails([FromRoute] string id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var tileDetails = _context.TileDetailsItems.Where(x => x.ESN == id);
if (tileDetails == null)
{
return NotFound();
}
return Ok(tileDetails);
}
// GET: api/UniqueOrders/000096543182
[HttpGet("UniqueOrders/{id}")]
public async Task<IActionResult> GetUniqueOrders([FromRoute] string id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var tileDetails = _context.TileDetailsItems
.Select(m => new {
m.AUFTRAG,
m.AUFTRAGSBEZ,
m.PMPS,
m.AUFTRAG_FERTIG_STATUS,
m.ESN
})
.Where(x => x.ESN == id)
.GroupBy(m => new {
m.AUFTRAG,
m.AUFTRAGSBEZ,
m.PMPS,
m.AUFTRAG_FERTIG_STATUS,
m.ESN
});
if (tileDetails == null)
{
return NotFound();
}
return Ok(tileDetails);
}
}
}
我究竟做错了什么?我的期望是这样的查询:
SELECT "m"."AUFTRAG", "m"."AUFTRAGSBEZ", "m"."PMPS", "m"."AUFTRAG_FERTIG", "m"."ESN"
FROM "SF"."WFD_MOTOR_EVENTS_AUFTRAEGE" "m"
GROUP BY "m"."AUFTRAG", "m"."AUFTRAGSBEZ", "m"."PMPS", "m"."AUFTRAG_FERTIG", "m"."ESN"
HAVING "m"."ESN" = '567274'
相反,这是生成的(“GROUP BY”子句在哪里???):
SELECT "m"."AUFTRAG", "m"."AUFTRAGSBEZ", "m"."PMPS", "m"."AUFTRAG_FERTIG", "m"."ESN"
FROM "SF"."WFD_MOTOR_EVENTS_AUFTRAEGE" "m"
WHERE "m"."ESN" = :id_0
ORDER BY "m"."AUFTRAG" NULLS FIRST, "m"."AUFTRAGSBEZ" NULLS FIRST, "m"."PMPS" NULLS FIRST, "m"."AUFTRAG_FERTIG" NULLS FIRST, "m"."ESN" NULLS FIRST
解决方案
在您的情况下,您的两个 sql 查询都是等效的。在“选择”部分,您具有与“组”部分相同的字段,并且没有任何聚合功能。中也没有聚合函数having
。所以having
在你的情况下像过滤器一样工作where
。
表达式GROUP BY "m"."AUFTRAG", "m"."AUFTRAGSBEZ", "m"."PMPS", "m"."AUFTRAG_FERTIG", "m"."ESN"
意味着您按第一个字段分组,然后按第二个等,还按第一个字段排序结果,然后按第二个等等。因为您在“选择”部分没有任何聚合功能,并且选择部分的字段是相同的在“group by”部分,编译器将 group by 更改为 order by。
但在我看来,编译器应该Distinct
在你的情况下添加到“选择”部分。
因此,您应该将代码简化为:
var tileDetails = _context.TileDetailsItems
.Where(x => x.ESN == id)
.Select(m => new {
m.AUFTRAG,
m.AUFTRAGSBEZ,
m.PMPS,
m.AUFTRAG_FERTIG_STATUS,
m.ESN
}).Distinct();
推荐阅读
- matplotlib - 在 plt.show() 之后绘图未显示,没有错误,仅显示:
- java - 服务中的 Android 位置管理器
- batch-file - 无法使用批处理脚本获取最新的 SVN 标记版本号
- python - 使用 psycopg2 批量更新 Postgres DB 中的行
- python - 为什么我不能将变量传递给 MySQLdb.connect()?
- latex - 如何打破包含连字符的长网址
- c# - 如何从 WPF 桌面应用程序检查 MSIX 更新?
- docker - 官方 nginx docker 在提供静态文件时给出 403 Forbidden
- regex - 正则表达式:如何在选择之前检查是否只有空格
- c++ - 将字符串中的元音加倍