考虑下面的代码行。
var query = ctx.Db.BannersV2.AsQueryable();
query = query.Where(v => v.IsEnable == true);
query = query.Where(v => (!v.StartdateTime.HasValue || v.StartdateTime <= date.Date) && (!v.EnddateTime.HasValue || v.EnddateTime >= date.Date));
query = query.Where(v => v.BannerType == bannerType);
if (categoryId.HasValue && query.Where(v => v.CategoryId != null).Any())
{
query = query.Where(v => v.CategoryId == categoryId.Value);
}
if (!location.IsNullOrBlank() && query.Any(v => !string.IsNullOrEmpty(v.Location)))
{
query = query.Where(v => v.Location.Contains(location));
}
if (!customerGroup.IsNullOrBlank() && query.Any(v => !string.IsNullOrEmpty(v.CustomerGroup)))
{
query = query.Where(v => v.CustomerGroup.Contains(customerGroup));
}
var result = query?.ToList();
这里我使用 AsQueryable(),然后使用 .Where() 谓词以及 .Any() 谓词。现在我担心或不确定,这个 .Any() 谓词是否会对数据库进行额外的调用?
或者当我使用 .ToList() 或 OrderBy() 或 Select() 时,只有它才会进行额外的数据库调用?
最佳答案
Any
是一个导致查询的操作 materialization ,例如ToList
, First
, Count
因此,在您的情况下,如果使用像 EF Core 这样的 ORM 之上的可查询构建,它将导致数据库调用(如果 categoryId.HasValue
是 true
)。最简单的检查选项是启用 EF 日志记录并检查输出。例如使用 simple logging :
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(Console.WriteLine);
根据提供的代码,似乎 Any
不过,调用是多余的,只需删除它们即可(遵循“标准” dynamic filtering pattern ):
if (categoryId.HasValue)
{
query = query.Where(v => v.CategoryId == categoryId.Value);
}
// ...
阅读更多/注释:
- 如果
Any
/ToList
/ETC。是实际查询的一部分,即在表达式树中使用(如query.Where(e => e.SomeCollection.Any())
),它不应导致额外的查询,而应转换为 SQL - What is the difference between
IQueryable<T>
andIEnumerable<T>
? - EF Core: How Queries Work
- ASP.NET Core 应用程序应启用 EF Core 日志记录 out of the box
关于c# - .Any() 是否进行额外的数据库调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77222171/