Я использую ASP.NET Core 2.1.1 с EF Core 2.1.4.
В моей базе данных приложений у меня есть Части, и у каждой Части есть свойства над ClusterPart: например, Список литературы.
Мои части кластера могут иметь прямые ссылки, такие как " B -> C " или двухэтапные ссылки, такие как " A -> B -> C ".
Я хочу инкапсулировать эту эталонную логику в вызов службы, который возвращает IQueryable, чтобы я мог использовать этот IQueryable для добавления еще большей информации в нескольких местах.
Служба для возврата указанных ClusterParts как IQueryable. Не тратьте слишком много времени на операторы linq:
public IQueryable<ClusterPart> GetReferencedClusterParts(long partId)
{
// Requested ClusterPart
var requestedClusterPart = _clusterPartDao.GetClusterPartsByPartId(partId)
.Include(cp => cp.Part)
.ThenInclude(p => p.Supplier)
.ThenInclude(s => s.SupplierType)
.FirstOrDefault();
// Get direct references B to C
var resultB2C = _clusterPartDao.GetAll() // This is just _context.Table
.Where(cpB => cpB.PartId.Equals(requestedClusterPart.PartId)) // Requested PartId
.SelectMany(cpB => cpB.ReferenceClusterPartIdFromNavigations) // Reference from A/B to C
.Select(rB2C => rB2C.ClusterPartIdToNavigation) // C ClusterPart
.Where(cpC => cpC.Part.Supplier.SupplierTypeId.Equals(1)) // SupplierType C
// Add 2 step references A to B to C
var resultA2B2C = _clusterPartDao.GetAll() // This is just _context.Table
.Where(cpA => cpA.PartId.Equals(requestedClusterPart.PartId)) // Requested PartId
.SelectMany(cpA => cpA.ReferenceClusterPartIdFromNavigations) // Reference from A to B
.Select(rA2B => rA2B.ClusterPartIdToNavigation) // B ClusterPart
.SelectMany(cpB => cpB.ReferenceClusterPartIdFromNavigations) // Reference from B to C
.Select(rB2C => rB2C.ClusterPartIdToNavigation) // B ClusterPart
.Where(cpC => cpC.Part.Supplier.SupplierTypeId.Equals(1)); // SupplierType C
return resultA2B2C.Union(resultB2C);
}
В основном я просто выбираю "C" ClusterParts, на которые ссылаются как "B -> C " и " A -> B -> C ".
Этот метод используется:
var resultCP = GetReferencedClusterParts(12345)
.Select(cpC => new ElementDTO
{
PartId = cpC.PartId,
PartName = cpC.Part.Name
});
result.References = resultCP.ToList();
Как только я нажимаю на resultCP.ToList (), запросы запускаются.
Это занимает очень много времени, так как LINQ решает выбрать полную таблицу «Часть», которая содержит 10 миллионов строк, если вызов GetReferencedClusterParts просто возвращает ~ 10 результатов. Я подтверждаю, что в SQL Server Profiler.
Когда я удаляю «cpC.Part.Name», таблица деталей выбирается не полностью.
Как я могу повлиять на эту ситуацию? Я хочу избежать того, чтобы EF Core или LINQ решили выбрать целую большую таблицу, а не просто объединить эту небольшую информацию с IQueryable, что было бы очень быстро, но я понятия не имею, почему таблица «Часть» полностью выбрана.