Linq-to-Entities:使用WHERE子句和投影LEFT OUTER JOIN

AJ.*_*AJ. 8 linq vb.net linq-to-entities left-join

我有一个heckuva时间弄清楚如何将带有两个条件where子句的简单SQL LEFT OUTER JOIN转换为一个有效的Linq-to-Entities查询.只有两张桌子.我需要Table1中所有行的值,无论Table2中的匹配如何,但WHERE子句使用Table2中的字段.在SQL中,两个参数是Table2WhereColumn1和Table2WhereColumn2,查询(可以工作)如下所示:

SELECT t1.Table1Id,
    t1.FieldDescription, 
    t2.FieldValue
FROM Table1 t1 WITH (NOLOCK)
LEFT JOIN Table2 t2 WITH (NOLOCK) ON t1.Table1Id = t2.Table1Id
WHERE (t2.Table2WhereColumn1 = @someId OR t2.Table2WhereColumn1 IS NULL)
AND (t2.Table2WhereColumn2 = @someOtherId OR t2.Table2WhereColumn2 IS NULL)
ORDER BY t1.OrderByColumn
Run Code Online (Sandbox Code Playgroud)

我尝试过使用Group Joinwith DefaultIfEmpty(),以及一个隐式连接(没有实际的Join关键字),我只获得表2中具有值的项的行.我相信这不会有帮助,但是这里有一个我一直在尝试的Linq的例子不起作用:

Public Shared Function GetProfilePreferencesForCedent(ByVal dc As EntityContext, _
                                                      ByVal where1 As Int32, _
                                                      ByVal where2 As Int32) _
                                                  As IQueryable(Of ProjectedEntity)
    Return From t1 In dc.Table1
           Group Join t2 In dc.Table2 _
                On t1.Table1Id Equals t2.Table1Id _
                Into t2g1 = Group _
           From t2gx In t2g1.DefaultIfEmpty(Nothing)
           Where (t2gx.Table2Where1 = where1 Or t2gx.Table2Where1 = Nothing) _
                And (t2gx.Table2Where2 = where2 Or t2gx.Table2Where2 = Nothing)
           Order By t1.SortOrder
           Select New ProjectedEntity With {
               .Table1Id = t1.Table1Id, _
               .FieldDescription = t1.FieldDescription, _
               .FieldValue = If(t2gx Is Nothing, String.Empty, t2gx.FieldValue) _
           }
End Function
Run Code Online (Sandbox Code Playgroud)

Eni*_*ity 12

请查看这些查询并告诉我它们是否适合您.我没有设置要测试的数据,但它们应该没问题.

请原谅我的C#和VB.NET的混合.我曾经是一名VB.NET开发人员,但在过去的几年里,我主要在C#工作,所以我现在感觉更舒服.

这是我为Table1&创建的类Table2:

public class Table1
{
    public int Table1Id { get; set; }
    public string FieldDescription { get; set; }
    public int OrderByColumn { get; set; }
}
public class Table2
{
    public int Table1Id { get; set; }
    public string FieldValue { get; set; }
    public int Table2WhereColumn1 { get; set; }
    public int Table2WhereColumn2 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在C#中的查询应该是:

var query =
    from t1 in Table1
    join t2 in Table2 on t1.Table1Id equals t2.Table1Id into _Table2
    from _t2 in _Table2.DefaultIfEmpty()
    where _t2 == null ? true :
        _t2.Table2WhereColumn1 == @someId
        && _t2.Table2WhereColumn2 == @someOtherId
    orderby t1.OrderByColumn
    select new
    {
        t1.Table1Id,
        t1.FieldDescription,
        FieldValue = _t2 == null ? "" : _t2.FieldValue,
    };
Run Code Online (Sandbox Code Playgroud)

并转换成VB.NET:

Dim query = _
    From t1 In Table1 _
    Group Join t2 In Table2 On t1.Table1Id Equals t2.Table1Id Into _Table2 = Group _
    From _t2 In _Table2.DefaultIfEmpty() _
    Where If(_t2 Is Nothing, True, _t2.Table2WhereColumn1 = someId AndAlso  _
                                   _t2.Table2WhereColumn2 = someOtherId) _
    Order By t1.OrderByColumn _
    Select New With { _
            .Table1Id = t1.Table1Id, _
            .FieldDescription = t1.FieldDescription, _
            .FieldValue = If(_t2 Is Nothing, "", _t2.FieldValue) _
        }
Run Code Online (Sandbox Code Playgroud)

如果他们有效,请告诉我.手指交叉.:-)


Jam*_*s S 5

就我个人而言,如果左连接的右侧有 where 条件,我通常更喜欢将它们放入连接标准中

在这种情况下,SQL 将如下所示:

SELECT t1.Table1Id,
       t1.FieldDescription, 
       t2.FieldValue
FROM Table1 t1 WITH (NOLOCK)
LEFT JOIN Table2 t2 WITH (NOLOCK) ON t1.Table1Id = t2.Table1Id 
                                  AND t2.Table2WhereColumn1 = @someId
                                  AND t2.Table2WhereColumn2 = @someOtherId
ORDER BY t1.OrderByColumn
Run Code Online (Sandbox Code Playgroud)

其 LINQ 代码(C# 语言)如下所示:

var query =
    from t1 in Table1
    join t2 in Table2 on new{a = t1.Table1Id, b = someId, c = someotherId} 
                         equals new {a = t2.Table1Id b = t2.Table2WhereColumn1, c = Table2WhereColumn2} 
    into _Table2
    from _t2 in _Table2.DefaultIfEmpty()
    orderby t1.OrderByColumn
    select new
    {
        t1.Table1Id,
        t1.FieldDescription,
        FieldValue = _t2 == null ? "" : _t2.FieldValue,
    };
Run Code Online (Sandbox Code Playgroud)

没有测试过 - 但应该可以