我最近一直在研究我的Web应用程序的性能,发现一些LINQ查询,我不确定更改它们是否可以提高性能。
基本上,当前代码如下:
var result = _carsRepository.GetAll()
.Where(x => x.Name == input.Name)
.FirstOrDefault();
if (result != null)
{
throw new Exception("test");
}
我正在考虑将其更改为:
var result = _carsRepository.GetAll()
.Where(x => x.Name == input.Name)
.Any();
if (result)
{
throw new Exception("test");
}
据我了解,第一个查询将返回一个实际的实体,我不需要,因为我只想知道数据库中是否已经存在具有相同名称的记录。第二个查询仅返回布尔值。
感谢您的任何评论。
编辑:我可能正在EF db上下文上运行查询,因此请忽略该内容。 当前存储库是通用的Abp.Domian.Repository。 GetAll()返回IQueryable
答案 0 :(得分:3)
我们无法告诉您,因为我们既不知道您的存储库类做什么,也不知道您的数据库驱动程序如何处理向SQL的转换。
同时测试它们,对其进行基准测试,查看SQL并使用数据库分析工具进行检查,以防您可能缺少索引或其他优化机会。
仅凭Linq就无法分辨。
答案 1 :(得分:3)
可能会有细微的差别,因为
.FirstOrDefault()
-读取所有列
.Any()
-只需检查是否有条目
差异将主要基于数据大小和SQL结构,索引及所有。建议通过测试对其进行基准测试
答案 2 :(得分:3)
我不确定GetAll()
会做什么。如果它将所有项目从数据库移动到本地内存,那么我不会打扰:尝试改进该语句。如果只需要第一个项目,为什么要提取所有项目。
如果GetAll()
返回IQueryable<...>
,则存在细微差别:
FirstOrDefault()
将更改查询中的表达式,这样SQL语句将为Select top 1 ... from
。
更改表达式后,它将要求Provider
的{{1}}执行IQqueryable
,SQL语句的完整结果将被转移到本地内存中,在这种情况下将是一项。
Expression
几乎会执行相同的操作,但SQL将是:Any()
很容易看到Select top 1 1 from ...
最多将传送一个整数,而Select top 1 1
将传送所有选定的列。
因此,如果您只想检查是否有任何元素,则Select top 1
比Any()
更有效率
答案 3 :(得分:2)
不。您可能不会获得任何性能差异。因为
1) Any()将在找到匹配项后立即返回。
2) FirstOrDefault()迭代(可能)在找到满足条件的元素时停止。
LINQ对象: Enumerable.Any 和 Enumerable.FirstOrDefault 应该执行相同的操作,因为它们的代码几乎相同:
第一个或默认值:
str(DT2_mat)
'data.frame': 5120 obs. of 7 variables:
$ : Factor w/ 2 levels "Archaea","Bacteria": 2 2 2 2 2 2 2 2 2 2 ...
..- attr(*, "names")= chr "P11_16513" "P193_8942" "P187_9526" "P11_4543" ...
$ : Factor w/ 28 levels "Acidobacteria",..: 2 2 2 2 2 2 2 2 2 2 ...
..- attr(*, "names")= chr "P11_16513" "P193_8942" "P187_9526" "P11_4543" ...
$ : Factor w/ 60 levels "Acidimicrobiia",..: 3 3 3 3 3 3 3 3 3 3 ...
..- attr(*, "names")= chr "P11_16513" "P193_8942" "P187_9526" "P11_4543" ...
$ : Factor w/ 108 levels "Acholeplasmatales",..: 29 29 29 29 29 29 29 29 29 29 ...
..- attr(*, "names")= chr "P11_16513" "P193_8942" "P187_9526" "P11_4543" ...
$ : Factor w/ 216 levels "0319-6A21","0319-6G20",..: 58 58 58 58 58 58 58 58 58 58 ...
..- attr(*, "names")= chr "P11_16513" "P193_8942" "P187_9526" "P11_4543" ...
$ : Factor w/ 699 levels "Abiotrophia",..: 173 173 173 173 173 173 173 173 173 173 ...
..- attr(*, "names")= chr "P11_16513" "P193_8942" "P187_9526" "P11_4543" ...
$ : Factor w/ 4964 levels "Abiotrophia defectiva Score:0.87",..: 1613 1529 1449 1448 1565 1438 1563 1532 1623 1605 ...
..- attr(*, "names")= chr "P11_16513" "P193_8942" "P187_9526" "P11_4543" ...
P
任何:
foreach (TSource source1 in source)
{
if (predicate(source1))
return source1;
}
return default (TSource);
现在。看起来您正在从内存中的数据库获取所有记录,然后应用where子句。
尝试避免一次在内存中加载数据,那样会给您带来性能上的差异
答案 4 :(得分:1)
如前所述,不清楚您的存储库做什么。但是,如果您遵循RepositoryPattern,则应考虑在存储库中添加Any作为方法。
public virtual bool Any(Expression<Func<T, bool>> predicate)
{
return _context.Set<T>().Any(predicate);
}
这将确保您的Any在数据库上执行,因为此方法以IQueryable的形式执行Any。
如果您没有在存储库中使用泛型,则将T替换为目标类。