C# 低效的LINQ—知道SQL应该是什么—可以';我到不了那里

C# 低效的LINQ—知道SQL应该是什么—可以';我到不了那里,c#,sql,sql-server,linq-to-sql,C#,Sql,Sql Server,Linq To Sql,我知道我要生成的SQL: SELECT qdt, pbn, cid, pid, SUM(Amount) AS TotalAmount FROM SomeDb.SomeTable WHERE Status = 'Open' GROUP BY cid, pid, qdt, pbn ORDER BY qdt 我有LINQ,我希望它能产生像上面SQL一样干净的东西: var query = ( from someTable in SomeTable where someTable.Status

我知道我要生成的SQL:

SELECT qdt, pbn, cid, pid, SUM(Amount) AS TotalAmount
FROM SomeDb.SomeTable
WHERE Status = 'Open'
GROUP BY cid, pid, qdt, pbn
ORDER BY qdt
我有LINQ,我希望它能产生像上面SQL一样干净的东西:

var query = (
  from someTable in SomeTable
  where someTable.Status == "Open"
  group someTable by new { someTable.cid, someTable.pid } into grouped
    select new
    {
      lid = grouped.FirstOrDefault().lid,
      qdt = grouped.FirstOrDefault().qdt,
      pbn = grouped.FirstOrDefault().pbn,
      cid = grouped.FirstOrDefault().cid,
      cn = grouped.FirstOrDefault().cn,
      pid = grouped.FirstOrDefault().pid,
      amount = grouped.Sum(o => o.Amount),
      Status = grouped.FirstOrDefault().Status
});
但这会产生许多令人讨厌的SQL语句。对于qdt,每个分组的值最终都会在查询中获得自己的SELECT语句,如下所示:

SELECT [t5].[qdt]
FROM (
    SELECT TOP (1) [t4].[qdt]
    FROM [SomeDb].[SomeTable] AS [t4]
    WHERE ([t1].[cid] = [t4].[cid]) AND ([t1].[pid] = [t4].[pid]) AND ([t4].[Status] = @p0)
    ) AS [t5]
) AS [qdt]

是否有办法更改LINQ以生成更简单的SQL?

您的LINQ中似乎没有所需SQL中的所有按列分组

var query = (
  from someTable in SomeTable
  where someTable.Status == "Open"
  group someTable by new { someTable.cid, someTable.pid, someTable.qdt,someTable.pbn, someTable.Status } into grouped
    select new
    {
      qdt = grouped.FirstOrDefault().qdt,
      pbn = grouped.FirstOrDefault().pbn,
      cid = grouped.FirstOrDefault().cid,
      pid = grouped.FirstOrDefault().pid,
      Status = grouped.FirstOrDefault().Status,
      amount = grouped.Sum(o => o.Amount)

});

我无法真正测试它,但它看起来更像是您试图在linq中复制的sql。

我发现您的linq尝试存在两个问题。首先,您在SQL查询中没有按照与LINQ中相同的字段进行分组。然后,对组的结果使用
FirstOrDefault
,而不是选择组的关键数据

您的查询应如下所示:

var query = 
(
    from someTable in SomeTable
    where someTable.Status == "Open"
    group someTable by new 
    { 
        someTable.lid, 
        someTable.qdt,
        someTable.pbn,
        someTable.cid,
        someTable.cn,
        someTable.pid,
        someTable.Status,
    } into grouped
    select new
    {
        lid = grouped.Key.lid,
        qdt = grouped.Key.qdt,
        pbn = grouped.Key.pbn,
        cid = grouped.Key.cid,
        cn = grouped.Key.cn,
        pid = grouped.Key.pid,
        amount = grouped.Sum(o => o.Amount),
        Status = grouped.Key.Status
    }
);

但是,我现在无法测试它是否会生成完全相同的SQL。

我从未在EF/Linq to SQL方面有过好运气。使用它们很难获得性能和效率。您最好使用ADO.NET或Dapper之类的微型ORM。是的,EF生成的SQL非常糟糕。我正在考虑ADO.NET。以前没有使用过Dapper。FirstOrDefault调用会破坏您的性能。@TravisJ它应该是什么呢?顺便说一句,Linq to EF很少生成与您相同的SQL,这没关系。密钥只是能够验证它是否生成功能等效的SQL,从而为您提供正确的结果和正确的性能。不应该
分组.FirstOrDefault().cid
分组.key.cid
?(与所有其他字段相同…)很可能不会产生相同的输出,除非添加的分组字段恰好在四个原始分组字段的每组中相同。看我在问题下面的评论:这个问题不现实。@GertArnold是的,我知道这个问题不现实,但这在清洁度和性能方面都应该更好。但当它不正确时,这并不重要。我想这是OP应该决定的。如果与
grouped.Key.Field
使用完全相同的分组字段,则输出应该是正确的,对吗?是的,但这只提供了四个字段。其他三个仍然需要
FirstOrDefault()
。(嗯,
状态
也可以是分组的一部分,因为您只查询一个
状态
)。