Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何防止在使用Union时生成外部Select语句?_C#_Entity Framework_Linq_Entity Framework Core - Fatal编程技术网

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是对的,这是一个完全不同的查询。谢谢