【问题标题】:how to concert SQL query to LINQ with count , group by and isnull clause如何使用 count 、 group by 和 isnull 子句协调 SQL 查询到 LINQ
【发布时间】:2019-04-22 12:46:09
【问题描述】:

我有以下 SQL 查询,我正在尝试将其转换为 LINQ 查询

SELECT C.NAME,C.MOBILEPHONE,ISNULL (SUM(P.PAYMENTAMOUNT),0)  AS 
PAYAMOUNT,BILLAMOUNT ,B.ID,BILLNO , BILLDATE FROM CUSTOMERS C
JOIN BILLS B ON B.CUSTOMERID=C.ID
LEFT JOIN BILLPAYMENTS P ON P.BILLID=B.ID
GROUP BY C.NAME ,B.BILLAMOUNT,B.ID,BILLNO,BILLDATE,C.MOBILEPHONE
HAVING B.BILLAMOUNT> ( ISNULL(SUM(P.PAYMENTAMOUNT),0)) 

您如何在 LINQ 中表示这一点?

我见过这个典型的实现

var query = from c in db.Customers
                    join b in db.Bills on c.Id equals b.CustomerId
                     join p in db.BillPayments on b.Id equals p.BillId into cs
                     from xx in cs.DefaultIfEmpty()

                    group xx by new { c.Name, c.MobilePhone, b.BillAmount, b.BillNo, b.Id, b.BillDate } into g
                    where g.Sum(p => p.PaymentAmount) < g.Key.BillAmount
                    select new
                    {
                        Received = g.Key,
                        ReceivedTotal =   g.Sum(p => p.PaymentAmount) 

                    };

但不确定如何实现以下内容:

 HAVING B.BILLAMOUNT> ( ISNULL(SUM(P.PAYMENTAMOUNT),0)) 

【问题讨论】:

标签: entity-framework linq sql-to-linq-conversion


【解决方案1】:

所以你有一个Customers 的序列,其中每个Customer 有零个或多个Bills,每个Bill 恰好属于一个Customer:一个简单的一对多关系。

此外,每个Bill 有零个或多个BillPayments,其中每个BillPayment 恰好属于一个Bill,也是一对多关系。

唉,你忘了告诉我们你的课程。如果您关注entity framework code first conventions,您将获得类似以下内容:

class Customer
{
     public int Id {get; set;}
     public string Name {get; set;}
     ...

     // every Customer has zero or more Bills (one-to-many)
     public virtual ICollection<Bill> Bills {get; set;}
}
class Bill
{
     public int Id {get; set;}
     public int BillNo {get; set;}
     public decimal BillAmount {get; set;}
     ...

     // every Bill belongs to exactly one Customer, using foreign key
     public int CustomerId {get; set;}
     public virtual Customer Customer {get; set;}

     // every Bill has zero or more BillPayments (one-to-many)
     public virtual ICollection<BillPayment> BillPayments {get; set;}
}
class BillPayment
{
     public int Id {get; set;}
     ...

     // every BillPayment belongs to exactly one Bill, using foreign key
     public int BillId {get; set;}
     public virtual Bill Bill{get; set;}

     // every Bill has zero or more BillPayments (one-to-many)
     public virtual ICollection<BillPayment> BillPayments {get; set;}
}

在实体框架中,你的表的列由非虚属性表示,虚属性表示表之间的关系。

您还忘记了查询的要求。在我看来,您想要以下内容:

给我账单的某些属性(Id、BillNo、BillDate、BillAmount),以及该账单的客户的某些属性(姓名和手机),以及所有尚未全额支付的账单。或者换句话说,在所有付款的总和小于 BillAmount 的所有账单中。

实体框架的优点之一是您不必自己进行连接,您可以使用虚拟属性。 Entity Framework 知道表之间的关系并为您执行正确的连接。

只是为了好玩,我们将添加原始的 BillAmount、AmountPaid 和 RemainingAmount,这样当您用手机给客户打电话时,您就可以告诉他还需要支付多少

在需求中,您看到了Bills 的核心作用,所以让我们以此为起点:

// (1) from all bills, calculate the AmountPaid; remember the original bill data:
var notFullyPaidBills = myDbContext.Bills
    .Select(bill => new
    {
        BillData = bill,
        AmountPaid = bill.BillPayments
          .Select(billPayment => billPayment.PaymentAmount)
          .Sum(),
    })
    // (2) Keep only those bills that are not fully paid yet
    .Where(bill => bill.Bil.BillAmount > bill.AmountPaid)

    // (3) from the remaining bills select the required properties:
    .Select(bill => new
    {
        // Customer properties:
        CustomerName = bill.BillData.Customer.Name,
        MobilePhone = bill.BillData.Customer.MobilePhone,

        // bill properties:
        BillId = bill.BillData.Id,
        BillNo = bill.BillData.BillNo,
        BillDate = bill.BillData.Date,

        // Amounts:
        BillAmount = bill.BillData.BillAmount,
        AmountPaid = bill.AmountPaid,
        RemainingAmount = bill.BillData.BillAmount - bill.AmountPaid,
    });

看到了吗?使用实体框架类的虚拟属性时,查询看起来比您自己进行(组)加入时更简单、更直观。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-08
    相关资源
    最近更新 更多