Как повлиять на LINQ с EntityFramework Ядра неправильно Выберите решения - PullRequest
0 голосов
/ 03 апреля 2019

Я использую ASP.NET Core 2.1.1 с EF Core 2.1.4.

В моей базе данных приложений у меня есть Части, и у каждой Части есть свойства над ClusterPart: например, Список литературы.

enter image description here

Мои части кластера могут иметь прямые ссылки, такие как " 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, что было бы очень быстро, но я понятия не имею, почему таблица «Часть» полностью выбрана.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...