【问题标题】:how can I translate my SQL statement to LINQ如何将我的 SQL 语句转换为 LINQ
【发布时间】:2017-10-06 17:41:16
【问题描述】:

我是 LINQ 的新手,对做一些简单的 LINQ 了解甚少。但现在,我所拥有的比我能做的更复杂。我已经创建了 SQL 语句,尝试过它并且它有效。但我无法将其翻译成 LINQ。

编辑:我尝试编写 linq 代码并创建了一个模型以将其显示到视图中。但是,我没有得到我想要的数据。我不知道我在哪里弄错了linq。请帮忙。

This are the tables involved, the output using SQL and output using LINQ

这是 SQL:

  select oh.date, oh.id, 
         od.TotalAmount, 
         CASE when oh.Discount_level = 2
            then ((od.TotalAmount / 1.12) * .2)
         END as Discount, 
         (od.TotalAmount / 1.12) as VATSale, 
         ((od.TotalAmount / 1.12) * .12) as VAT,
         CASE when oh.Discount_level = 2
            then ((od.TotalAmount / 1.12) * .8)
            when oh.Discount_level = 1
            then od.TotalAmount
         END as AmountDue
  from Order_Header oh
  inner join 
  ( 
    select Order_Header_id, SUM(price * quantity) as TotalAmount
    from Order_Details
    group by Order_Header_id
  ) od
  on oh.id = od.Order_Header_id;

我拥有的 linq:

  var list = (from oh in db.Order_Header
                 join iq in (
                                from t in db.Order_Details
                                group t by t.Order_Header_id
                                into g
                                select new
                                {
                                    ohId = g.Key,
                                    totalAmount = ((from t2 in db.Order_Details select t2.price * t2.quantity)).Max()
                                }
                             )
                 on oh.id equals iq.ohId
                 select new Report
                 {
                     date = oh.date,
                     ohId = iq.ohId,
                     totalAmount = iq.totalAmount,
                     discount = oh.Discount_level == 2 ? (iq.totalAmount /1.12) * 2 : 0 ,
                     VATSale = iq.totalAmount / 1.12,
                     VAT = (iq.totalAmount / 1.12) * .12,
                     amountDue = oh.Discount_level == 2 ? ((iq.totalAmount / 1.12) * .8) * 2 : iq.totalAmount
                 }).ToList();

报告模型:

public class Report
{
    public DateTime? date  { get; set;  }

    public int ohId  { get; set;  }

    public double totalAmount { get; set; }

    public double discount { get; set; }

    public double VATSale { get; set; }

    public double VAT { get; set; }

    public double amountDue { get; set; }

}

【问题讨论】:

  • 向我们展示您迄今为止为使用 LINQ 所做的尝试。任何努力都是好的。
  • 嗯,有趣的是,它将涉及至少两个投影 (.Select)。好吧,有些人需要在沉迷于此类查询之前看到您的努力。只是一点点线索,您可以在 linq 中放入内联条件 - 传说中的 <condition> ? <if_pass> : <otherwise>,例如.Select(x => x.DiscountLevel == 2 ? ((x.TotalAmount / 1.12) * 0.8) : ....).
  • 另外,如果您发布Order_HeaderOrder_Details的结构会有所帮助。
  • 是的,我刚刚上传了一张桌子的照片。
  • 好吧,我正在起草我的答案。哈哈。无论如何,编码愉快。

标签: sql-server asp.net-mvc linq


【解决方案1】:

假设您的 POCO 模型如下所示:

    public class Order_Header
    {
        public Guid Id { get; set; }
        public int Discount_Level { get; set; }
        public Order_Detail Order_Detail {get;set;}
    }

    public class Order_Detail
    {
        public Guid Order_Header_Id { get; set; }
        public double Price { get; set; }
        public int Quantity { get; set; }
        public Order_Header Order_Header { get; set; }
    }

并让ods 作为IDbSet<Order_Detail> 实例在DbContext 中。 您可以像这样将上面的查询翻译成 Lambda LINQ。

    var odproj = ods.GroupBy(x => x.Order_Header_Id)
                    .Select(x => new { Order_Header = x.First().Order_Header,
                                       TotalAmount = x.Sum(y => y.Price * y.Quantity)})
                    .Select(x => new { Order_Header = x.Order_Header,
                                       Id = x.Order_Header.Id,
                                       TotalAmount = x.TotalAmount,
                                       Discount = (x.Order_Header.Discount_Level == 2 ? ((x.TotalAmount / 1.12) * 0.2) : 0),
                                       VATSale = (x.TotalAmount / 1.12),
                                       VAT = ((x.TotalAmount / 1.12) * 0.12),
                                       AmountDue = ((x.Order_Header.Discount_Level == 2) ? ((x.TotalAmount / 1.12) * 0.8)
                                                                                         : (x.Order_Header.Discount_Level == 1 ? x.TotalAmount : 0)
                                                   )
                     });

说明 首先,我们基于Order_Header(一个)对Order_Detail(很多)进行分组,以定义单个交易(在POS系统意义上就是这样)。分组后,我们根据订单的价格和数量“计算”总金额。总价计算在第一个 Select 中完成,它生成一个具有 2 个字段的匿名类,一个保留 Order_Header 信息,另一个保留我们想要的信息。下一个Select 我们计算折扣、VATSale 等——第一个子句中的复杂 if-else。

附言。我还没有在 EF 中尝试过,我的 RAM 太小而无法启动 SQL Server。用谷物和盐来接受这个想法。这个问题的关键角,我有点犹豫的是 EF 是否会识别Order_Header = x.First().Order_Header。尽管如此,使用 LINQ 足以保证您使用繁重的OUTER JOIN,这可能最终导致您的查询被 SQL 执行计划程序丢弃。如果它太复杂,只需创建一个STORED PROCEDURE 并拉起一个edmx 来映射它(等等,Code First 可以做到这一点吗?我很想知道)。

【讨论】:

  • 成功了!谢谢!如果你不介意,我可以再问你一件事吗?如果我想有参数怎么办?比如StartDateEndDate。我刚刚意识到有时我想获取特定日期范围内的行。
  • 嗯,最好稍微挖掘一下stackoverflow .. 我想有人已经问过了。如果没有,请在另一个问题中提出并具体说明字段类型。尽管如此,编码愉快。
猜你喜欢
  • 2011-01-24
  • 2021-12-17
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多