[英]EF-Core Method Call in LINQ Performance
this problem is not about async problems with entityframework itself as discussed here . 这个问题与这里讨论的实体框架本身的异步问题无关。
In the method CalculateSomething
you can see two LINQ-Calls. 在
CalculateSomething
方法中,您可以看到两个LINQ调用。 The performance of the first LINQ-Call (initializing result
) is absolutely okay. 第一次LINQ-Call(初始化
result
)的性能绝对可以。
However, the performance of the second LINQ-Call (initializing resultWithDate
) Is way slower than the first one. 但是,第二个LINQ-Call(初始化
resultWithDate
)的性能比第一个慢。
The first one takes 2 Seconds, The second one takes 15-20 Seconds. 第一个花费2秒,第二个花费15-20秒。
dataBase
is my DbContext
class. dataBase
是我的DbContext
类。 Iam using Entity Framework Core. 我使用实体框架核心。
private async Task<long> CalculateSomething(string numberOne, MyStatus status)
{
var result = await this.dataBase.Something.CountAsync(item => item.NumberOne== numberOne && item.Status == (short)status);
var resultWithDate = await this.dataBase.Something.CountAsync(item => item.NumberOne== numberOne && item.Status == (short)status && !this.IsOlderThan30Days(item.Date));
return result;
}
private bool IsOlderThan30Days(DateTime? itemDate)
{
bool result = true;
if (itemDate.HasValue)
{
if ((DateTime.Now - itemDate.Value).TotalDays <= 30)
{
result = false;
}
}
return result;
}
The problem is not the method call IsOlderThan30Days
, the problem is about CountAsync
. 问题不在于方法调用
IsOlderThan30Days
,而是与CountAsync
有关。 I know this because I had something like this: 我知道这是因为我有这样的事情:
private async Task<long> CalculateAmountOfOrders(string numberOne, MyStatus status)
{
var result = this.dataBase.Something.Where(item => item.NumberOne == numberOne && item.Status == (short)status);
var resultWithDate = this.dataBase.Something.Where(item => item.NumberOne == numberOne && item.Status == (short)status && !this.IsOlderThan30Days(item.Date));
var resultCount = await result.CountAsync();
var resultWithDateCount = await resultWithDate.CountAsync();
return resultCount;
}
And the performance loss appeared at the two CountAsync()
calls. 并且性能损失出现在两个
CountAsync()
调用中。 CountAsync
on resultWithDateCount
took 15 seconds while CountAsync
on resultCount
only took 2 seconds. CountAsync
上resultWithDateCount
花了15秒,而CountAsync
上resultCount
只用了2秒。 initializing result
and resultWithDate
was equally fast. 初始化
result
和resultWithDate
速度同样快。
Am I doing something wrong? 难道我做错了什么?
Thank you 谢谢
Try this: 尝试这个:
var date = DateTime.Now.AddDays(-30);
var result = await this.dataBase.Something.CountAsync(item => item.NumberOne == numberOne && item.Status == (short)status);
var resultWithDate = itemDate.HasValue ? await this.dataBase.Orders.CountAsync(item => item.NumberOne == numberOne && item.Status == (short)status &&
itemDate.Value < date) : 0;
Or alternatively: 或者:
var date = DateTime.Now.AddDays(-30);
var result = await this.dataBase.Something.CountAsync(item => item.NumberOne == numberOne && item.Status == (short)status);
var resultWithDate = await this.dataBase.Orders.CountAsync(item => item.NumberOne == numberOne && item.Status == (short)status &&
itemDate < date);
The key is trying to do the 30 day date calculation outside of the LINQ. 关键是试图在LINQ 之外进行30天日期计算。
Ok here is a code inspired from @mjwills : 好的,这是一个受@mjwills启发的代码:
private async Task<long> CalculateSomething(string numberOne, MyStatus status)
{
var date = DateTime.Now.AddDays(-30);
var result = await this.dataBase.Something.CountAsync(item =>
item.NumberOne == numberOne && item.Status == (short)status);
var resultWithDate = await this.dataBase
.Something
.CountAsync(item => item.NumberOne == numberOne && item.Status == (short)status && (!item.Date.HasValue || item.Date.Value <= date));
return result;
}
The problem is that IsOlderThan30Days
forces loading data into memory. 问题是
IsOlderThan30Days
强制将数据加载到内存中。 You should be able to gain some performance by doing the computation in the database: 您应该能够通过在数据库中进行计算来获得一些性能:
var now = DateTime.Now;
var resultWithDate = await this.dataBase
.Something
.CountAsync(item =>
item.NumberOne== numberOne
&& item.Status == (short)status
&& (item.Date != null && EntityFunctions.DiffDays(item.Date, now) <= 30)
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.