如何使用EntityFramework Cores影响LINQ错误的选择决策

时间:2019-04-03 15:09:55

标签: c# performance linq asp.net-core entity-framework-core

我正在将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);
}

基本上,我只是选择引用为“ B-> C ”和“ A-> B-> C ”之类的“ C” ClusterParts。

此方法供以下人员使用:

var resultCP = GetReferencedClusterParts(12345)
    .Select(cpC => new ElementDTO
    {
        PartId = cpC.PartId,
        PartName = cpC.Part.Name
    });
result.References = resultCP.ToList();

我一点击resultCP.ToList(),查询就会被触发。 由于LINQ决定选择包含1000万行的完整表“ Part”,因此花费的时间非常长,如果调用“ GetReferencedClusterParts”仅返回约10个结果。我在SQL Server Profiler中证实了这一点。

当我删除“ cpC.Part.Name”时,“ Part”表未完全选中。

我如何影响这种情况?我想避免EF Core或LINQ决定选择整个大表,而不是只将很少的信息加入到IQueryable中,这很快,但是我不知道为什么完全选择了表“ Part”。

0 个答案:

没有答案