如何在Linq中将此查询写入实体:
SELECT * FROM TableA a LEFT JOIN TableB b ON a.Id = b.TableAId WHERE ISNULL(b.Id) OR b.FieldA = 1
关系是1对多,但限制b.FIeldA = 1确保返回的实际数据为1-0 ... 1,这意味着返回的记录数应等于TableA中的记录。我需要从TableA获取所有数据,并从TableB中加入存在的数据。我正在尝试使用这个查询,它实际上像INNER JOIN一样预先形成(TableA中的记录没有在TableB中没有相关记录)
Vladislav建议在下面查询,我在第一次查询中添加了额外的过滤:
var query = (from x in myParentClasses.Include(x => x.TableBChildren)
where !x.TableBChildren.Any(y => y.FieldA == 1)
select x)
.Concat(
from x in myParentClasses.Include(x => x.TableBChildren)
where x.TableBChildren.Any(y => y.FieldA == 1 || y.Id == null)
select x)
.ToList();
生成的sql如下所示:
SELECT [Project1][...]
FROM (SELECT [Extent1].[...],
[Extent2].[...],
[Extent3].[...],
CASE
WHEN ([Extent3].[Id] IS NULL) THEN CAST(NULL AS int)
ELSE 1
END AS [C1]
FROM [dbo].[ParentTable] AS [Extent1]
LEFT OUTER JOIN [dbo].[ReferenceTable] AS [Extent2]
ON [Extent1].[ReferenceId] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[ChildrenTable] AS [Extent3]
ON [Extent1].[Id] = [Extent3].[ParentId]
WHERE [Extent1].[FieldA] = 1 /* @p__linq__0 */) AS [Project1]
ORDER BY [Project1].[Id] ASC,
[Project1].[Id1] ASC,
[Project1].[C1] ASC
谢谢, 戈兰
答案 0 :(得分:0)
Linq-to-entities与SQL完全不同。只有在您的查询允许时才执行左连接(除非您手动编写连接,否则您无法手动控制该行为)。这不是您的查询的情况,因为它使用x.TableBChildren.Any
=它要求父表具有满足条件的子表中的任何记录,因此它使用内部联接。
我没有尝试过,可能有更好的方法,但我认为这可行:
var query = (from x in myParentClasses.Include(x => x.TableBChildren)
where !x.TableBChildren.Any()
select x)
.Concat(
from x in myParentClasses.Include(x => x.TableBChildren)
where x.TableBChildren.Any(y => y.FieldA == 1 || y.Id == null)
select x)
.ToList();
第一部分选择所有没有相关实体的记录,第二部分选择满足条件的相关实体的记录。它将这两部分联合起来。
另请注意,Include
不会过滤您的关系 - 它会每次都选择所有关系。如果你想过滤它们,你必须用投影编写查询。
编辑:
如果您希望过滤TableB
,则无法使用普通查询和Include
。您也无法返回MyParentClass
的实例。你必须使用投影:
var query = from x in myParentClasses
select new
{
Id = x.Id,
// Rest of properties from myParentClass you want to receive
TableBChildren = x.TableBChildren.Where(y => y.FieldA == 1 || y.Id == null)
};
这将返回带有过滤的TableB
s的匿名类型。无法投影到映射实体(MyParentClass
)。