C# 如何防止在使用Union时生成外部Select语句?
我有如下几点:C# 如何防止在使用Union时生成外部Select语句?,c#,entity-framework,linq,entity-framework-core,C#,Entity Framework,Linq,Entity Framework Core,我有如下几点: var peopleFromPhones = _context.Phones.Where(p => p.PhoneNumber.StartsWith(searchVM.Phone)) .Join(_context.People, phone => phone.ContactID, person => person.Con
var peopleFromPhones = _context.Phones.Where(p => p.PhoneNumber.StartsWith(searchVM.Phone))
.Join(_context.People,
phone => phone.ContactID,
person => person.ContactID,
(phone, person) => new Person()
{
FirstName = person.FirstName,
LastName = person.LastName
})
.Select(a => new
{
Name = a.FirstName + " " + a.LastName
})
;
var orgsFromPhones = _context.Phones.Where(p => p.PhoneNumber.StartsWith(searchVM.Phone))
.Join(_context.Organizations,
phone => phone.ContactID,
org => org.ContactID,
(phone, org) => new Organization()
{
BusinessName = org.BusinessName
})
.Select(b => new
{
Name = b.BusinessName
})
var results = peopleFromPhones.Union(orgsFromPhones) //UNION HERE
var items = results.Skip(skip).Take(searchVM.Rows).AsEnumerable()
.Select(x => new SearchContactResultVM()
{
Name = x.Name
})
.ToList();
但当我查看生成的SQL时:
SELECT TOP(@__p_1) [t].[MemberNumber], [t].[Email], [t].[ContactId], [t].[PersOrgNbr], [t].[Name], [t].[DOB], [t].[SIN]
FROM (
SELECT [c].[MemberNumber], [c].[Email], [p0].[ContactID] AS [ContactId], [p0].[PersNbr] AS [PersOrgNbr], ([p0].[FirstName] + N' ') + [p0].[LastName] AS [Name], CASE
WHEN [p0].[DateOfBirth] IS NOT NULL THEN CONVERT(VARCHAR(100), [p0].[DateOfBirth])
ELSE N''
END AS [DOB], [p0].[SIN]
FROM [Phones] AS [p]
INNER JOIN [People] AS [p0] ON [p].[ContactID] = [p0].[ContactID]
INNER JOIN [Contacts] AS [c] ON [p0].[ContactID] = [c].[ContactID]
WHERE (@__searchVM_Phone_0 = N'') OR ([p].[PhoneNumber] IS NOT NULL AND (LEFT([p].[PhoneNumber], LEN(@__searchVM_Phone_0)) = @__searchVM_Phone_0))
UNION ALL
SELECT [c0].[MemberNumber], [c0].[Email], [o].[ContactID] AS [ContactId], [o].[OrgNbr] AS [PersOrgNbr], [o].[BusinessName] AS [Name], N'' AS [DOB], N'' AS [SIN]
FROM [Phones] AS [p1]
INNER JOIN [Organizations] AS [o] ON [p1].[ContactID] = [o].[ContactID]
INNER JOIN [Contacts] AS [c0] ON [o].[ContactID] = [c0].[ContactID]
WHERE (@__searchVM_Phone_0 = N'') OR ([p1].[PhoneNumber] IS NOT NULL AND (LEFT([p1].[PhoneNumber], LEN(@__searchVM_Phone_0)) = @__searchVM_Phone_0))
) AS [t]
ORDER BY [t].[Name]
有一个不必要的Select语句妨碍了ORDER BY的执行。我发现,如果删除外部Select,查询运行速度会快得多
有没有办法防止EntityFramework生成这个不必要的Select语句?我相信它来自工会
编辑:下面是我想要的更快的查询:
SELECT TOP(@__p_1) [c].[MemberNumber], [c].[Email], [p0].[ContactID] AS [ContactId], [p0].[PersNbr] AS [PersOrgNbr], ([p0].[FirstName] + N' ') + [p0].[LastName] AS [Name], CASE
WHEN [p0].[DateOfBirth] IS NOT NULL THEN CONVERT(VARCHAR(100), [p0].[DateOfBirth])
ELSE N''
END AS [DOB], [p0].[SIN]
FROM [Phones] AS [p]
INNER JOIN [People] AS [p0] ON [p].[ContactID] = [p0].[ContactID]
INNER JOIN [Contacts] AS [c] ON [p0].[ContactID] = [c].[ContactID]
WHERE (@__searchVM_Phone_0 = N'') OR ([p].[PhoneNumber] IS NOT NULL AND (LEFT([p].[PhoneNumber], LEN(@__searchVM_Phone_0)) = @__searchVM_Phone_0))
UNION ALL
SELECT [c0].[MemberNumber], [c0].[Email], [o].[ContactID] AS [ContactId], [o].[OrgNbr] AS [PersOrgNbr], [o].[BusinessName] AS [Name], N'' AS [DOB], N'' AS [SIN]
FROM [Phones] AS [p1]
INNER JOIN [Organizations] AS [o] ON [p1].[ContactID] = [o].[ContactID]
INNER JOIN [Contacts] AS [c0] ON [o].[ContactID] = [c0].[ContactID]
WHERE (@__searchVM_Phone_0 = N'') OR ([p1].[PhoneNumber] IS NOT NULL AND (LEFT([p1].[PhoneNumber], LEN(@__searchVM_Phone_0)) = @__searchVM_Phone_0))
ORDER BY [Name]
我在SSMS中测试了它,它似乎在对结果列表排序,而不仅仅是对联合的后半部分排序。你所说的不必要的选择是什么意思 使用results.Skipskip.TakesearchVM.Rows调用进行分页查询时需要外部选择 如果SQL Select部件处于禁用状态,则此查询中不需要执行以下操作: 挑选TOP@__p_1[t].[MemberNumber]、[t].[Email]、[t].[ContactId]、[t].[PersOrgNbr]、[t].[Name]、[t].[DOB]、[t].[SIN] 这里不需要全部结果,只需要为C SearchContactResultVM模型获取[t].[Name] 要删除rest SELECT列,请尝试以下代码:
var items = results.Skip(skip).Take(searchVM.Rows)
.Select(n => n.Name).AsEnumerable()
.Select(name => new SearchContactResultVM()
{
Name = name
})
.ToList();
我取消了.AsEnumerable调用,因此Select将应用于SQL查询本身您确定编辑后的第二个查询按预期工作吗 我在以下SQL中简化并复制了相同的逻辑:
DECLARE @A AS TABLE ([Name] NVARCHAR(50));
DECLARE @B AS TABLE ([Name] NVARCHAR(50));
INSERT INTO @A VALUES ('a'), ('c'), ('e'), ('g');
INSERT INTO @B VALUES ('b'), ('d'), ('f'), ('h');
SELECT TOP(3) [Name]
FROM @A
UNION ALL
SELECT [NAME]
FROM @B
ORDER BY [Name]
您可以假设该值为:
Name
a
b
c
但事实上,在回报方面:
Name
a
b
c
d
e
f
h
它从@A取了前3名,然后应用了UNION ALL,然后进行排序,总的来说,它返回7行如果没有外部选择,我不清楚查询如何能够有一个有意义的ORDER BY,因为它可能只是对UNION ALL的后半部分进行排序。您能否显示您认为更快的查询,以便我们进行比较?另外,请确保您问题中的代码确实编译了,但现在没有。我尝试更改输出查询,结果表明您可以直接在联合上应用分页+排序。另外,我尝试了您的更改,它使我无法将lambda表达式转换为string类型,因为它不是委托类型。我调整了SelectYou是对的,这是一个完全不同的查询。谢谢