我有一个heckuva时间弄清楚如何将一个简单的SQL LEFT OUTER JOIN转换为一个带有两个条件的where子句到一个工作的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
我已尝试将Group Join
与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
答案 0 :(得分:10)
查看这些查询并告诉我它们是否适合您。我没有设置要测试的数据,但它们应该没问题。
请原谅我的C#& amp; 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; }
}
现在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,
};
转换成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) _
}
如果他们有效,请告诉我。手指交叉。 : - )
答案 1 :(得分:4)
就个人而言,如果左边连接的右边有条件,我通常更喜欢将它们加入连接标准
在这种情况下,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
这个(在C#中)的LINQ代码如下所示:
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,
};
没有测试过 - 但是应该可以工作
答案 2 :(得分:0)
我不赞成这个答案,但它很华丽:LINQ to SQL - Left Outer Join with multiple join conditions
基本上,在子查询上使用扩展方法where子句但必须在DefaultIfEmpty()
之前使用它:
from p in context.Periods
join f in context.Facts on p.id equals f.periodid into fg
from fgi in fg.Where(f => f.otherid == 17).DefaultIfEmpty()
where p.companyid == 100
select f.value