使用Entity Framework将T-SQL转换为LINQ

3
我正在尝试将我的T-SQL转换为LINQ语句,但却令我感到头痛。请问有人能指出我在这里做错了什么吗?
T-SQL
select 
  h.DateStamp
, h.Machine
, h.SalesInvoice 
, h.Status
, sum(i.Quantity)                                           totalquantity
, sum(IIF(h.[Status]='SALES', i.Quantity, 0))               as SalesQty
, sum(IIF(h.[Status]='RETURNS', i.Quantity, 0))             as ReturnQty
, sum(IIF(h.[Status]='SALES',   i.Quantity*i.Soldsrp , 0))  as SalesGross
, sum(IIF(h.[Status]='RETURNS', i.Quantity*i.Soldsrp, 0))   as ReturnGross
, sum(IIF(h.[Status]='SALES',   i.DiscountAmount , 0))      as SalesDiscount
, sum(IIF(h.[Status]='RETURNS', i.DiscountAmount, 0))       as ReturnDiscount
, sum(IIF(h.[Status]='SALES',   i.TotalAmount , 0))         as SalesACD
, sum(IIF(h.[Status]='RETURNS', i.TotalAmount , 0))         as ReturnACD

from CSHR_SalesItems i
left join CSHR_SalesHeader h on h.SalesOrderNum = i.SalesOrderNum
where H.DateStamp between '2015-08-20 00:00:00.000' and '2015-08-27 23:59:00.000' 

group by h.DateStamp, h.Machine, h.SalesInvoice, h.[Status]

这是我尝试使用Entity Framework将其转换为LINQ。GroundCommander是实体。

using (var GC = new GroundCommanderEntities())
{
    foreach (var item in GC.CSHR_SalesItems)
    {
         var Summary =
             from i in GC.CSHR_SalesItems
             join h in GC.CSHR_SalesHeader on item.SalesOrderNum equals h.SalesOrderNum into IH
             from h in IH
             where (h.DateStamp >= dateTimePickerStart.Value && h.DateStamp <= dateTimePickerLast.Value)                 
             select new { 
                h.DateStamp,
                h.Machine,
                h.SalesInvoice,
                h.Status,
                i.Quantity //need to get the sum
             };
    }

你需要使用 from h in IH.DefaultIfEmpty() 来实现左连接。 - juharr
谢谢,我没有注意到。 - J.P Masangcay
虽然我认为你根本不需要左连接,因为当左侧为空时,where条件将会是false。 - juharr
EF是否在CSHR_SalesItems中创建了一个导航属性,以便为您提供CSHR_SalesHeader中的值列表?使用它比一开始就进行连接更容易。 - juharr
没有创建导航属性。 - J.P Masangcay
1个回答

1
我相信这就是你想要的。
var Summary =
    from i in GC.CSHR_SalesItems
    join h in GC.CSHR_SalesHeader on item.SalesOrderNum equals h.SalesOrderNum 
    where (h.DateStamp >= dateTimePickerStart.Value 
           && h.DateStamp <= dateTimePickerLast.Value)      
    group new { item = i, header = h} 
       by new {h.DateStamp, h.Machine, h.SalesInvoice, h.Status} into grp
    select new { 
        grp.Key.DateStamp,
        grp.Key.Machine,
        grp.Key.SalesInvoice,
        grp.Key.Status,
        TotalQuanity = grp.Sum(x => x.item.Quantity),
        SalesQty = grp.Where(x => x.header.Status == "SALES").Sum(x => x.item.Quantity),
        ...
    };

首先我已经摆脱了左连接,因为任何时候右侧为空(null),那么where语句将会是假的。第二,我添加了分组操作,这样可以创建适当的分组。然后,在选择语句中,您可以进行总和计算,并且我已经为您提供了如何根据状态过滤其他总数的示例。

我很好奇这会生成什么SQL语句,并且是否与手写编码一样高效。 - Dai
你可以使用SQL Server Profiler来查看创建了什么。通常情况下,EF SQL更难阅读。你可以在SSMS中运行两者,以查看执行计划是否有所不同。 - juharr
我现在正在尝试它。到目前为止,阅读代码看起来是正确的。谢谢到目前为止。 - J.P Masangcay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接