LINQ:左连接而不是内连接

时间:2013-03-06 08:15:20

标签: .net linq tsql linq-to-entities left-join

我有一个问题:

    var groups = query
                .Where(x => x.CrossSearchArticle == searchParameters.SearchString)
                .Join(RuntimeValues.Context.SiteBrands,
                      cross => cross.CrossBrandID,
                      brand => brand.SiteBrandsID,
                      (cross, brand) => new { cross, brand })
                .GroupBy(x => x.cross.CrossGroupID)
                .Select(x => new ProductClarify
                        {
                           CrossGroupID = x.Key,
                           CrossGroupName = x.Max(z => z.cross.CrossGroupName),
                           SourceArticle = x.Max(z => z.cross.SourceArticle),
                           SiteBrandName = x.Max(z => z.brand.Name)
                        });

此查询转换为T-SQL,如下所示:

    SELECT 
    1 AS [C1], 
    [GroupBy1].[K1] AS [CrossGroupID], 
    [GroupBy1].[A1] AS [C2], 
    [GroupBy1].[A2] AS [C3], 
    [GroupBy1].[A3] AS [C4]
    FROM ( SELECT 
        [Extent1].[CrossGroupID] AS [K1], 
        MAX([Extent1].[CrossGroupName]) AS [A1], 
        MAX([Extent1].[SourceArticle]) AS [A2], 
        MAX([Extent2].[Name]) AS [A3]
        FROM  [dbo].[ArticlesCrosses] AS [Extent1]
        INNER JOIN [dbo].[SiteBrands] AS [Extent2] 
           ON [Extent1].[CrossBrandID] = [Extent2].[SiteBrandsID]
        WHERE [Extent1].[CrossSearchArticle] = @p__linq__0
        GROUP BY [Extent1].[CrossGroupID]
    )  AS [GroupBy1]

我需要用LEFT JOIN替换INNER JOIN。不多也不少。 我尝试了一些带有.DefaultIfEmpty()的变体,但它不能按照我想要的方式工作。 这是我的研究:

    var groups = query
                .Where(x => x.CrossSearchArticle == searchParameters.SearchString)
                .Join(RuntimeValues.Context.SiteBrands.DefaultIfEmpty(),
                       cross => cross.CrossBrandID,
                       brand => brand.SiteBrandsID,
                       (cross, brand) => new { cross, brand })
                .GroupBy(x => x.cross.CrossGroupID)
                .Select(x => new ProductClarify
                    {
                        CrossGroupID = x.Key,
                        CrossGroupName = x.Max(z => z.cross.CrossGroupName),
                        SourceArticle = x.Max(z => z.cross.SourceArticle),
                        SiteBrandName = x.Max(z => z.brand.Name)
                    });

转换为:

        SELECT 
        1 AS [C1], 
        [GroupBy1].[K1] AS [CrossGroupID], 
        [GroupBy1].[A1] AS [C2], 
        [GroupBy1].[A2] AS [C3], 
        [GroupBy1].[A3] AS [C4]
        FROM ( SELECT 
            [Extent1].[CrossGroupID] AS [K1], 
            MAX([Extent1].[CrossGroupName]) AS [A1], 
            MAX([Extent1].[SourceArticle]) AS [A2], 
            MAX([Join1].[Name]) AS [A3]
            FROM  [dbo].[ArticlesCrosses] AS [Extent1]
            INNER JOIN  (SELECT [Extent2].[SiteBrandsID] AS [SiteBrandsID], 
                                [Extent2].[Name] AS [Name]
                FROM   ( SELECT 1 AS X ) AS [SingleRowTable1]
                LEFT OUTER JOIN [dbo].[SiteBrands] AS [Extent2] ON 1 = 1 ) AS [Join1] 
    ON ([Extent1].[CrossBrandID] = [Join1].[SiteBrandsID]) 
        OR (([Extent1].[CrossBrandID] IS NULL) AND ([Join1].[SiteBrandsID] IS NULL))
            WHERE [Extent1].[CrossSearchArticle] = @p__linq__0
            GROUP BY [Extent1].[CrossGroupID]
        )  AS [GroupBy1]

和这一个

    var groups = query
                .Where(x => x.CrossSearchArticle == searchParameters.SearchString)
                    .Join(RuntimeValues.Context.SiteBrands,
                          cross => cross.CrossBrandID,
                          brand => brand.SiteBrandsID,
                          (cross, brand) => new { cross, brand })
                    .DefaultIfEmpty()
                    .GroupBy(x => x.cross.CrossGroupID)
            .Select(x => new ProductClarify
                        {
                           CrossGroupID = x.Key,
                           CrossGroupName = x.Max(z => z.cross.CrossGroupName),
                           SourceArticle = x.Max(z => z.cross.SourceArticle),
                           SiteBrandName = x.Max(z => z.brand.Name)
                        });

转换为

    SELECT 
    1 AS [C1], 
    [GroupBy1].[K1] AS [CrossGroupID], 
    [GroupBy1].[A1] AS [C2], 
    [GroupBy1].[A2] AS [C3], 
    [GroupBy1].[A3] AS [C4]
    FROM ( SELECT 
        [Project1].[CrossGroupID] AS [K1], 
        MAX([Project1].[CrossGroupName]) AS [A1], 
        MAX([Project1].[SourceArticle]) AS [A2], 
        MAX([Project1].[Name]) AS [A3]
        FROM   ( SELECT 1 AS X ) AS [SingleRowTable1]
        LEFT OUTER JOIN  (SELECT 
            [Extent1].[CrossGroupID] AS [CrossGroupID], 
            [Extent1].[CrossGroupName] AS [CrossGroupName], 
            [Extent1].[SourceArticle] AS [SourceArticle], 
            [Extent2].[Name] AS [Name]
            FROM  [dbo].[ArticlesCrosses] AS [Extent1]
            INNER JOIN [dbo].[SiteBrands] AS [Extent2] 
                       ON [Extent1].[CrossBrandID] = [Extent2].[SiteBrandsID]
            WHERE [Extent1].[CrossSearchArticle] = @p__linq__0 ) AS [Project1] 
                  ON 1 = 1
        GROUP BY [Project1].[CrossGroupID]
    )  AS [GroupBy1]

我不知道怎么做。伙计们需要帮助!

1 个答案:

答案 0 :(得分:0)

这是一种作弊方式。如果你真的只想用左连接替换内连接。在生产环境中不太合适。它确实有效但=)

DataContext ctx = yourcontext;
var x = from a in atable
    join b in btableon a.key equals b.key
    select a; //returns atype
string sql = ctx.GetCommand(x).CommandText;
var y = ctx.ExecuteQuery(typeof(atype),sql.Replace("INNER JOIN","LEFT JOIN"));
y.Dump();

- )