C# 在LINQ中左连接到实体?
我正在尝试LINQ到实体 我有以下问题: 我希望它能做到这一点:C# 在LINQ中左连接到实体?,c#,linq,entity-framework,entity-framework-4,linq-to-entities,C#,Linq,Entity Framework,Entity Framework 4,Linq To Entities,我正在尝试LINQ到实体 我有以下问题: 我希望它能做到这一点: SELECT T_Benutzer.BE_User ,T_Benutzer_Benutzergruppen.BEBG_BE FROM T_Benutzer LEFT JOIN T_Benutzer_Benutzergruppen ON T_Benutzer_Benutzergruppen.BEBG_BE = T_Benutzer.BE_ID 最接近我的是: var lol = (
SELECT
T_Benutzer.BE_User
,T_Benutzer_Benutzergruppen.BEBG_BE
FROM T_Benutzer
LEFT JOIN T_Benutzer_Benutzergruppen
ON T_Benutzer_Benutzergruppen.BEBG_BE = T_Benutzer.BE_ID
最接近我的是:
var lol = (
from u in Repo.T_Benutzer
//where u.BE_ID == 1
from o in Repo.T_Benutzer_Benutzergruppen.DefaultIfEmpty()
// on u.BE_ID equals o.BEBG_BE
where (u.BE_ID == o.BEBG_BE || o.BEBG_BE == null)
//join bg in Repo.T_Benutzergruppen.DefaultIfEmpty()
// on o.BEBG_BG equals bg.ID
//where bg.ID == 899
orderby
u.BE_Name ascending
//, bg.Name descending
//select u
select new
{
u.BE_User
,o.BEBG_BG
//, bg.Name
}
).ToList();
但这将生成与内部联接相同的结果,而不是左联接。此外,它还创建了一个完全疯狂的SQL:
SELECT
[Extent1].[BE_ID] AS [BE_ID]
,[Extent1].[BE_User] AS [BE_User]
,[Join1].[BEBG_BG] AS [BEBG_BG]
FROM [dbo].[T_Benutzer] AS [Extent1]
CROSS JOIN
(
SELECT
[Extent2].[BEBG_BE] AS [BEBG_BE]
,[Extent2].[BEBG_BG] AS [BEBG_BG]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
LEFT OUTER JOIN [dbo].[T_Benutzer_Benutzergruppen] AS [Extent2]
ON 1 = 1
) AS [Join1]
WHERE [Extent1].[BE_ID] = [Join1].[BEBG_BE]
OR [Join1].[BEBG_BE] IS NULL
ORDER BY [Extent1].[BE_Name] ASC
如何在LINQ-2-entities中以如下方式进行左连接:
另一个人仍然可以理解代码中正在做什么
最好是生成的SQL如下所示:
SELECT
T_Benutzer.BE_User
,T_Benutzer_Benutzergruppen.BEBG_BE
FROM T_Benutzer
LEFT JOIN T_Benutzer_Benutzergruppen
ON T_Benutzer_Benutzergruppen.BEBG_BE = T_Benutzer.BE_ID
你可以阅读我为LINQ中的joins写的一篇文章 以下是使用扩展方法的等效项:
var query =
Repo.T_Benutzer
.GroupJoin
(
Repo.T_Benutzer_Benutzergruppen,
x=>x.BE_ID,
x=>x.BEBG_BE,
(o,i)=>new {o,i}
)
.SelectMany
(
x => x.i.DefaultIfEmpty(),
(o,i) => new
{
BE_User = o.o.BE_User,
BEBG_BG = (int?)i.BEBG_BG
}
);
啊,是我自己弄的LINQ-2-实体的怪癖和夸克。
这看起来很容易理解:
var query2 = (
from users in Repo.T_Benutzer
from mappings in Repo.T_Benutzer_Benutzergruppen
.Where(mapping => mapping.BEBG_BE == users.BE_ID).DefaultIfEmpty()
from groups in Repo.T_Benutzergruppen
.Where(gruppe => gruppe.ID == mappings.BEBG_BG).DefaultIfEmpty()
//where users.BE_Name.Contains(keyword)
// //|| mappings.BEBG_BE.Equals(666)
//|| mappings.BEBG_BE == 666
//|| groups.Name.Contains(keyword)
select new
{
UserId = users.BE_ID
,UserName = users.BE_User
,UserGroupId = mappings.BEBG_BG
,GroupName = groups.Name
}
);
var xy = (query2).ToList();
删除.DefaultIfEmpty()
,您将获得一个内部联接。这就是我想要的。您不仅可以在实体中使用它,还可以在存储过程或其他数据源中使用它:
var customer = (from cus in _billingCommonservice.BillingUnit.CustomerRepository.GetAll()
join man in _billingCommonservice.BillingUnit.FunctionRepository.ManagersCustomerValue()
on cus.CustomerID equals man.CustomerID
// start left join
into a
from b in a.DefaultIfEmpty(new DJBL_uspGetAllManagerCustomer_Result() )
select new { cus.MobileNo1,b.ActiveStatus });
也许我稍后会来回答,但现在我面临着这个问题。。。如果有帮助,还有一个解决方案(我解决它的方式)
顺便说一句,我试着使用Stefan Steiger代码,这也有帮助,但速度非常慢。简单的方法是使用Let关键字。这对我有用
from AItem in Db.A
Let BItem = Db.B.Where(x => x.id == AItem.id ).FirstOrDefault()
Where SomeCondition
Select new YourViewModel
{
X1 = AItem.a,
X2 = AItem.b,
X3 = BItem.c
}
这是一个左连接的模拟。如果B表中的每个项目与某个项目不匹配,BItem return nullDuplicate-@Anand:Nope,join总是产生内部联接,并且从没有条件的情况下是交叉联接,所选的答案是错误的和不充分的,尽管它有许多UPVOUTS,但相关的post-可能重复但投票率最高的答案会生成左外部联接,据林帕德说。(可能自2014年以来情况发生了变化?)你在这里的回答也一样,但更简洁,所以我喜欢。它是T_Benutzer_Benutzergruppen,不是T_Benutzergruppen,但在其他方面是正确的。只是想知道当连接两个以上的表时,这应该如何工作。我在寻找一种更直观易懂的方法。我终于发现了:)就我个人而言,我已经习惯了扩展方法之一,我真的很喜欢它。如果您不断重复
GroupJoin
和SelectMany
情侣,您可以有一个不错的解决方案,虽然很长:)您是否有机会在Linq-2-Objects中这样做?因为在那里它会很慢,因为它不使用索引。太好了!第一次看到这样的东西。使用DefaultIfEmpty模拟查询时出错。从这里得到了创建默认类“a.DefaultIfEmpty(new DJBL_uspGetAllManagerUserCustomer_Result())”的想法,并且成功了!不幸的是,创建实体会使集成测试失败,所以这不是一个好的解决方案。这正是我的5表查询所需要的!!!非常感谢你发布这篇文章,它让我省去了几个小时的头疼
var query2 = (
from users in Repo.T_Benutzer
join mappings in Repo.T_Benutzer_Benutzergruppen on mappings.BEBG_BE equals users.BE_ID into tmpMapp
join groups in Repo.T_Benutzergruppen on groups.ID equals mappings.BEBG_BG into tmpGroups
from mappings in tmpMapp.DefaultIfEmpty()
from groups in tmpGroups.DefaultIfEmpty()
select new
{
UserId = users.BE_ID
,UserName = users.BE_User
,UserGroupId = mappings.BEBG_BG
,GroupName = groups.Name
}
);
from AItem in Db.A
Let BItem = Db.B.Where(x => x.id == AItem.id ).FirstOrDefault()
Where SomeCondition
Select new YourViewModel
{
X1 = AItem.a,
X2 = AItem.b,
X3 = BItem.c
}