我有SQL 2008服务器,其中包含员工,电话和电子邮件,其中员工与电话和电子邮件处于一对多关系(因此员工可以拥有多个电话号码和电子邮件)。
现在我想用所有手机和电子邮件查询员工:
var query = (from e in db.Employee
select new EmployeeDTO
{
Id = e.Id,
Name = e.Name,
Phones = e.Phones,
Emails = e.Emails
}).ToList();
但是linq将它转换为非常丑陋的sql,它使得左边的联接与电话表,但然后它在单独的查询中查询每个员工的电子邮件,如:
SELECT [t0].[EmployeeID], [t0].[Name], [t1].[Phone] (
SELECT COUNT(*)
FROM [dbo].[Phone] AS [t2]
WHERE [t2].[EmployeeID] = [t0].[EmployeeID]
) AS [value]
FROM [dbo].[Employee] AS [t0]
LEFT OUTER JOIN [dbo].[Phone] AS [t1] ON [t1].[EmployeeID] = [t0].[EmployeeID]
ORDER BY [t0].[EmployeeID], [t1].[PhoneID]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926
SELECT [t0].[EmailID], [t0].[Email]
FROM [dbo].[Email] AS [t0]
WHERE [t0].[EmployeeID] = @x1
-- @x1: Input UniqueIdentifier (Size = 0; Prec = 0; Scale = 0) [1ed2e9a0-ca4b-4912-8f8e-000ed8d0b2af]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926
SELECT [t0].[EmailID], [t0].[Email]
FROM [dbo].[Email] AS [t0]
WHERE [t0].[EmployeeID]= @x1
-- @x1: Input UniqueIdentifier (Size = 0; Prec = 0; Scale = 0) [2203192b-05ef-4b59-b4b4-0010e26a8119]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926
我需要的是简单的sql:
SELECT [t0].[EmployeeID], [t0].[Name], [t1].[Phone], [t2].[Email]
FROM [dbo].[Employee] AS [t0]
LEFT OUTER JOIN [dbo].[Phone] AS [t1] ON [t1].[EmployeeID] = [t0].[EmployeeID]
LEFT OUTER JOIN [dbo].[Email] AS [t2] ON [t2].[EmployeeID] = [t0].[EmployeeID]
如何在不对结果进行分组的情况下编写此类linq查询? 我知道如何进行多次左连接,但后来我需要按EmployeeID对结果进行分组。
答案 0 :(得分:0)
你试过这样做吗?
var query = (from e in db.Employee
join p in db.Phones on e.EmployeeID equals p.EmployeeID into tmpPhones
from phones in tmpPhones.DefaultIfEmpty()
join m in db.Emails on e.EmployeeID equals m.EmployeeID into tmpEmails
from emails in tmpEmails.DefaultIfEmpty()
select new EmployeeDTO
{
Id = e.Id,
Name = e.Name,
Phones = phones,
Emails = emails
}).ToList();
你需要的是LoadWith来处理多个1到多个关系,但这不起作用 -
跳过篮球应该有效 -
var query = (from e in db.Employee
join p in db.Phones on e.EmployeeID equals p.EmployeeID into tmpPhones
from phones in tmpPhones.DefaultIfEmpty()
join m in db.Emails on e.EmployeeID equals m.EmployeeID into tmpEmails
from emails in tmpEmails.DefaultIfEmpty()
group e by e into eGrp
select new EmployeeDTO
{
Id = eGrp.Key.Id,
Name = eGrp.Key.Name,
Phones = eGrp.Select(x => x.Phones),
Emails = eGrp.Select(x => x.Emails)
}).ToList();