每当我在IQueryable上调用接受IEnumerable的扩展方法时,使用该列表/实体的过程的其余部分都会非常缓慢。
POR QUEEEEE?!
该问题似乎与代码的实际结构无关,因为它是最佳选择,当我启动一个新数据库进行单元测试时,该问题似乎没有出现。
这是扩展方法:
public static Bill FirstById(this IEnumerable<Bill> query, int billId)
{
return query.FirstOrDefault(r => r.Id == billId);
}
使用方法如下:
public Bill GetDeposit(int depositId)
{
var deposit = _depositRepository
.AndSalesOrder()
.AndSalesOrderCustomerContact()
.AndDepositApplications()
.FirstById(depositId);
return deposit;
}
这是实际实体的使用方式:
public bool ConvertDeposit(List<ConvertDepositSubmitModel> conversions)
{
if (conversions.Any())
{
var depositId = conversions.Select(c => c.DepositId)
.Distinct()
.Single();
var billPaymentIds = conversions.Select(c => c.BillPaymentId);
var deposit = _dataProvider.GetDeposit(depositId);
var billPayments = _dataProvider.GetBillPayments(billPaymentIds);
var totalConversionAmount = conversions.Sum(c => c.Amount);
var unappliedDepositAmount = (deposit.BillStatusId == BillStatus.Credited ? 0 : deposit.TotalSell - deposit.Balance) - deposit.DepositApplications.Select(a => a.Amount).DefaultIfEmpty(0).Sum();
if (unappliedDepositAmount != totalConversionAmount)
{
throw new Exception("The provided conversion amount would not fully convert the Deposit.");
}
_unitOfWork.TryTransactionAndCommit(() =>
{
foreach (var conversion in conversions)
{
var billPayment = billPayments.FirstByBillPaymentId(conversion.BillPaymentId);
this.CreateBillPaymentBill(deposit, conversion);
this.CreateMoneyOnAccountTransaction(deposit, conversion);
this.UpdateBillPayment(conversion, billPayment);
}
this.UpdateNetProceeds(billPayments);
this.ApplyCreditCardFees(billPaymentIds);
var customerCredit = this.CreateCustomerCredit(deposit, totalConversionAmount);
this.CreateCustomerCreditBill(deposit, customerCredit);
this.UpdateDeposit(deposit, totalConversionAmount);
});
}
else
{
throw new Exception("The provided set of bill payments was empty.");
}
return true;
}
我们看到,每种经过严格测试的方法都可以产生以下诊断结果:
PV2ANZAC
GetDeposit: 33434ms
GetBillPayments: 54ms
CreateBillPaymentBill1: 17775ms
CreateMoneyOnAccountTransaction1: 10774ms
UpdateBillPayment1: 10810ms
UpdateNetProceeds: 18130ms
ApplyCreditCardFees: 17206ms
Insert CustomerCredit: 10795ms
CustomerCredit SaveChanges: 16276ms
CreateCustomerCredit: 27075ms
CreateCustomerCreditBill: 10688ms
我们绝对希望所有事物都比它至少少一个数量级。
答案 0 :(得分:0)
为什么要创建一个接受IEnumerable的扩展方法?
很显然,当您在IQueryable上调用IEnumerable扩展方法时,IQueryable将会被水化,当您只需要一个时,便会在Bill表中引入每一行!
现在,如果我们可以假定GetBillPayments正在类似地调用数据库,则可以在这里解释差异:
GetDeposit: 33434ms
GetBillPayments: 54ms
答案 1 :(得分:0)
检查以下两件事:
1)您正在使用更改跟踪,这可能会导致速度缓慢。参见:https://weblog.west-wind.com/posts/2014/dec/21/gotcha-entity-framework-gets-slow-in-long-iteration-loops#Turn-off-Change-Tracking。
2)您要从数据库中提取一堆记录,然后在内存中查询该记录集,而不是在数据库级别查询您想要的记录。检查EF发送的查询,并确保没有在存储库级别实现该列表。