优化IQueryable空值检查实现:避免重复查询代码及解决IAsyncQueryProvider异常问题
Hey there! Let's clean up that redundant null check and fix the IAsyncQueryProvider issue you're hitting. Here are two straightforward solutions to streamline your code:
Solution 1: Initialize with an EF Core-compatible empty IQueryable
The problem with Enumerable.Empty<Customer>().AsQueryable() is that it creates an in-memory query provider, which doesn’t play nice with EF Core’s async operations. Instead, use EF Core itself to create an empty query that uses the correct provider:
// Initialize with an EF Core-supported empty query (returns no rows) IQueryable<Customer> customers = _context.Customers.Take(0); // Now you can safely Concat without any null checks customers = customers.Concat(_context.Developers .Include(s => s.Project) .ThenInclude(op => op.Customer) .Where(developer => developer.DeveloperId == userId) .Select(developer => developer.Project.Customer));
This works because Take(0) generates a valid EF Core query that returns no results, and it uses the same IAsyncQueryProvider as your other context queries—so async methods like ToListAsync() will work without throwing exceptions.
Solution 2: Extract the query logic to avoid repetition
If you prefer not to initialize with an empty set, you can pull the repeated developer customer query into a variable, then use a null check to simplify the assignment:
// Define your core query once (no more duplicate code!) var developerCustomersQuery = _context.Developers .Include(s => s.Project) .ThenInclude(op => op.Customer) .Where(developer => developer.DeveloperId == userId) .Select(developer => developer.Project.Customer); // Use a null check to handle the initial null state cleanly IQueryable<Customer> customers = customers == null ? developerCustomersQuery : customers.Concat(developerCustomersQuery);
This cuts down on code duplication immediately, and you don’t have to repeat the entire Include/Where/Select chain twice.
Bonus: Super concise (and safe) version
If you want to combine the best of both, you can even use this one-liner (still relying on the EF Core-compatible empty set):
var developerCustomersQuery = _context.Developers .Include(s => s.Project) .ThenInclude(op => op.Customer) .Where(developer => developer.DeveloperId == userId) .Select(developer => developer.Project.Customer); customers = (customers ?? _context.Customers.Take(0)).Concat(developerCustomersQuery);
All of these approaches eliminate messy null checks and duplicate query code, while ensuring your async operations work as expected.
内容的提问来源于stack exchange,提问作者Rida M

