我尝试将以下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))
答案 0 :(得分:0)
因此,您有一个Customers
序列,其中每个Customer
具有零个或多个Bills
,而每个Bill
恰好属于一个Customer
:简单的一对多关系。
此外,每个Bill
都有零个或多个BillPayments
,其中每个BillPayment
恰好属于一个Bill
,也是一对多的关系。
A,您忘了告诉我们您的课程。如果您遵循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,
});
看到了吗?使用实体框架类的虚拟属性时,查询将比您(组)加入自己时看起来更简单和直观。