Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 优化LINQ到SQL查询_C#_Linq_Linq To Sql - Fatal编程技术网

C# 优化LINQ到SQL查询

C# 优化LINQ到SQL查询,c#,linq,linq-to-sql,C#,Linq,Linq To Sql,我有一个非常繁重的LINQ到SQL查询,它对不同的表进行大量的连接以返回匿名类型。问题是,如果返回的行数量相当大(>200),那么查询速度就会非常慢,最终超时。我知道我可以增加数据上下文超时设置,但这是最后的选择 我只是想知道如果我将查询拆分,并将其作为LINQ与Object查询进行比较,是否会更好地工作,这样我甚至可以使用PLINQ最大限度地提高处理能力。但我觉得这对我来说是一个陌生的概念,我不知道该如何把它分开。有人能提供一些建议吗?我不是要求为我编写代码,只是提供一些关于如何改进的一般性指

我有一个非常繁重的LINQ到SQL查询,它对不同的表进行大量的连接以返回匿名类型。问题是,如果返回的行数量相当大(>200),那么查询速度就会非常慢,最终超时。我知道我可以增加数据上下文超时设置,但这是最后的选择

我只是想知道如果我将查询拆分,并将其作为LINQ与Object查询进行比较,是否会更好地工作,这样我甚至可以使用PLINQ最大限度地提高处理能力。但我觉得这对我来说是一个陌生的概念,我不知道该如何把它分开。有人能提供一些建议吗?我不是要求为我编写代码,只是提供一些关于如何改进的一般性指导

注意,我已经确保数据库中有我加入的所有正确的密钥,并且我已经确保这些密钥是最新的

查询如下:

var cons = (from c in dc.Consignments
            join p in dc.PODs on c.IntConNo equals p.Consignment into pg
            join d in dc.Depots on c.DeliveryDepot equals d.Letter
            join sl in dc.Accounts on c.Customer equals sl.LegacyID
            join ss in dc.Accounts on sl.InvoiceAccount equals ss.LegacyID
            join su in dc.Accounts on c.Subcontractor equals su.Name into sug
            join sub in dc.Accountsubbies on ss.ID equals sub.AccountID into subg
            where (sug.FirstOrDefault() == null
                || sug.FirstOrDefault().Customer == false)
            select new
            {
                 ID = c.ID,
                 IntConNo = c.IntConNo,
                 LegacyID = c.LegacyID,
                 PODs = pg.DefaultIfEmpty(),
                 TripNumber = c.TripNumber,
                 DropSequence = c.DropSequence,
                 TripDate = c.TripDate,
                 Depot = d.Name,
                 CustomerName = c.Customer,
                 CustomerReference = c.CustomerReference,
                 DeliveryName = c.DeliveryName,
                 DeliveryTown = c.DeliveryTown,
                 DeliveryPostcode = c.DeliveryPostcode,
                 VehicleText = c.VehicleReg + c.Subcontractor,
                 SubbieID = sug.DefaultIfEmpty().FirstOrDefault().ID.ToString(),
                 SubbieList = subg.DefaultIfEmpty(),
                 ScanType = ss.PODScanning == null ? 0 : ss.PODScanning
            });
以下是根据请求生成的SQL:

    {SELECT [t0].[ID], [t0].[IntConNo], [t0].[LegacyID], [t6].[test], [t6].[ID] AS [ID2], [t6].[Consignment], [t6].[Status], [t6].[NTConsignment], [t6].[CustomerRef], [t6].[Timestamp], [t6].[SignedBy], [t6].[Clause], [t6].[BarcodeNumber], [t6].[MainRef], [t6].[Notes], [t6].[ConsignmentRef], [t6].[PODedBy], (
    SELECT COUNT(*)
    FROM (
        SELECT NULL AS [EMPTY]
        ) AS [t10]
    LEFT OUTER JOIN (
        SELECT NULL AS [EMPTY]
        FROM [dbo].[PODs] AS [t11]
        WHERE [t0].[IntConNo] = [t11].[Consignment]
        ) AS [t12] ON 1=1 
    ) AS [value], [t0].[TripNumber], [t0].[DropSequence], [t0].[TripDate], [t1].[Name] AS [Depot], [t0].[Customer] AS [CustomerName], [t0].[CustomerReference], [t0].[DeliveryName], [t0].[DeliveryTown], [t0].[DeliveryPostcode], [t0].[VehicleReg] + [t0].[Subcontractor] AS [VehicleText], CONVERT(NVarChar,(
    SELECT [t16].[ID]
    FROM (
        SELECT TOP (1) [t15].[ID]
        FROM (
            SELECT NULL AS [EMPTY]
            ) AS [t13]
        LEFT OUTER JOIN (
            SELECT [t14].[ID]
            FROM [dbo].[Account] AS [t14]
            WHERE [t0].[Subcontractor] = [t14].[Name]
            ) AS [t15] ON 1=1 
        ORDER BY [t15].[ID]
        ) AS [t16]
    )) AS [SubbieID], 
    (CASE 
        WHEN [t3].[PODScanning] IS NULL THEN @p0
        ELSE [t3].[PODScanning]
     END) AS [ScanType], [t3].[ID] AS [ID3]
FROM [dbo].[Consignments] AS [t0]
INNER JOIN [dbo].[Depots] AS [t1] ON [t0].[DeliveryDepot] = [t1].[Letter]
INNER JOIN [dbo].[Account] AS [t2] ON [t0].[Customer] = [t2].[LegacyID]
INNER JOIN [dbo].[Account] AS [t3] ON [t2].[InvoiceAccount] = [t3].[LegacyID]
LEFT OUTER JOIN ((
        SELECT NULL AS [EMPTY]
        ) AS [t4]
    LEFT OUTER JOIN (
        SELECT 1 AS [test], [t5].[ID], [t5].[Consignment], [t5].[Status], [t5].[NTConsignment], [t5].[CustomerRef], [t5].[Timestamp], [t5].[SignedBy], [t5].[Clause], [t5].[BarcodeNumber], [t5].[MainRef], [t5].[Notes], [t5].[ConsignmentRef], [t5].[PODedBy]
        FROM [dbo].[PODs] AS [t5]
        ) AS [t6] ON 1=1 ) ON [t0].[IntConNo] = [t6].[Consignment]
WHERE ((NOT (EXISTS(
    SELECT TOP (1) NULL AS [EMPTY]
    FROM [dbo].[Account] AS [t7]
    WHERE [t0].[Subcontractor] = [t7].[Name]
    ORDER BY [t7].[ID]
    ))) OR (NOT (((
    SELECT [t9].[Customer]
    FROM (
        SELECT TOP (1) [t8].[Customer]
        FROM [dbo].[Account] AS [t8]
        WHERE [t0].[Subcontractor] = [t8].[Name]
        ORDER BY [t8].[ID]
        ) AS [t9]
    )) = 1))) AND ([t2].[Customer] = 1) AND ([t3].[Customer] = 1)
ORDER BY [t0].[ID], [t1].[ID], [t2].[ID], [t3].[ID], [t6].[ID]
}

试着将分包商的连接移到更高的位置,并将where条款与之一起推。这样,您就不会不必要地进行最终会失败的连接。 我还将修改分包商id的select,这样您就不会得到可能为空值的id

var cons = (from c in dc.Consignments
            join su in dc.Accounts on c.Subcontractor equals su.Name into sug
            where (sug.FirstOrDefault() == null || sug.FirstOrDefault().Customer == false)
            join p in dc.PODs on c.IntConNo equals p.Consignment into pg
            join d in dc.Depots on c.DeliveryDepot equals d.Letter
            join sl in dc.Accounts on c.Customer equals sl.LegacyID
            join ss in dc.Accounts on sl.InvoiceAccount equals ss.LegacyID                   
            join sub in dc.Accountsubbies on ss.ID equals sub.AccountID into subg
            let firstSubContractor = sug.DefaultIfEmpty().FirstOrDefault()
            select new
            {
                           ID = c.ID,
                           IntConNo = c.IntConNo,
                           LegacyID = c.LegacyID,
                           PODs = pg.DefaultIfEmpty(),
                           TripNumber = c.TripNumber,
                           DropSequence = c.DropSequence,
                           TripDate = c.TripDate,
                           Depot = d.Name,
                           CustomerName = c.Customer,
                           CustomerReference = c.CustomerReference,
                           DeliveryName = c.DeliveryName,
                           DeliveryTown = c.DeliveryTown,
                           DeliveryPostcode = c.DeliveryPostcode,
                           VehicleText = c.VehicleReg + c.Subcontractor,
                           SubbieID = firstSubContractor == null ? "" : firstSubContractor.ID.ToString(),
                           SubbieList = subg.DefaultIfEmpty(),
                           ScanType = ss.PODScanning == null ? 0 : ss.PODScanning
              });

在后台执行的SQL是什么?查询计划是什么样子的?我很好奇,如果选择存储过程中的所有记录,使用IMultilpleResults调用它,那么在内存中执行连接不会更快。您确定Linq在一个语句中完成所有操作(而不是每选择一行额外的语句)-不100%确定在“选择新方案”中这是否可行,所以请像@Heinzi所说的那样:您需要查看使用探查器生成的SQL或记录您的datacontextI不确定LINQ在您的方案中是否正确。我会选择常规存储过程(我们打赌它快多少?:p)。虽然我喜欢LINQ,但当您有这样复杂的连接时,通常最好将其封装在单个存储过程中,然后通过LINQ获得存储过程的结果。此外,我可能错了,但真正的性能问题可能是在您的where条款中。考虑将它更改为外部连接(在SQL中)。