Linq to Entities具有多个相关实体性能和UNION

时间:2014-10-19 23:41:01

标签: sql-server linq entity-framework projection

我正在构建搜索逻辑(对于MVC应用程序)并简单地说 - 我被卡住了!

我花了几天时间构建Linq to Entities查询以使用投影。在我查看下面生成的SQL语句之前,一切都很好。哇!

我接下来又花了几天时间试图从SQL语句中删除这些UNION语句,尝试JOIN,FROM,INCLUDE,任何只会给我内部/左外连接加载相关实体的内容。

但是我还没有成功地做到这一点并且仍然坚持到这一点。

需要考虑的一些要点:

  • L2E查询包含多个带投影的相关(子)实体(此处没有问题,除非这是一个糟糕的设计,即导致UNION)
  • 创建适合匿名类型的摘要类,例如: StudentSummary
  • 由于性能原因,摘要类仅包含实体对象列的一些列 - 不需要在初始搜索时返回所有列
  • 最近开始使用PredicateBuilder从搜索中返回学生,例如有专业的男学生......这方面都很好(到目前为止)。

这是我迄今为止所做的事情(代码更改为隐藏专有财产 - 可能有拼写错误):

    query = from s in context.Students
    select new StudentSummary
    {
        StudentID = s.StudentID,
        Title = s.Title,
        FullName = s.FullName,
        Qualifications = s.Qualifications,
        Gender = s.Gender,
        CampusSummaries = (
                    from c in s.Campuses
                    select new CampusSummary
                    {
                        Name = c.Name,
                        LocationSummary = new LocationSummary
                        {
                            State = c.Location.State
                        }
                    }),
                    SpecializationSummaries = (
                                    from sp in s.StudentSpecializations
                                    select new StudentSpecializationSummary
                                        {
                                            StudentSpecializationID = sp.StudentSpecializationID,
                                            SpecializationSummary = new SpecializationSummary
                                            {
                                                Name = s.Specialization.Name
                                            }
                                        }),
                    SubSpecializationSummaries = (
                                    from ssp in s.StudentSubSpecializations
                                    select new StudentSubSpecializationSummary
                                        {
                                            StudentSubSpecializationID = ssp.StudentSubSpecializationID,
                                            SubSpecializationSummary = new SubSpecializationSummary
                                            {
                                                Name = s.SubSpecialization.Name
                                            }
                                        })
};

我的投影语句似乎使Entity Framework生成以下SQL UNION语句,下面只是一个片段(代码更改为隐藏专有属性 - 可能有拼写错误):

{SELECT 
[UnionAll1].[StudentID] AS [C1], 
[UnionAll1].[StudentID1] AS [C2], 
[UnionAll1].[Title] AS [C3], 
[UnionAll1].[FullName] AS [C4], 
[UnionAll1].[Qualifications] AS [C5], 
[UnionAll1].[Gender] AS [C6], 
[UnionAll1].[C1] AS [C9], 
[UnionAll1].[StudentSpecializationID] AS [C10], 
[UnionAll1].[StudentSpecializationID1] AS [C11], 
[UnionAll1].[StudentSpecializationID2] AS [C12], 
[UnionAll1].[Name] AS [C13], 
[UnionAll1].[C2] AS [C14], 
[UnionAll1].[C3] AS [C15], 
[UnionAll1].[C4] AS [C16], 
[UnionAll1].[C5] AS [C17]
FROM  (SELECT 
    CASE WHEN ([Join1].[StudentSpecializationID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1], 
    [Extent1].[StudentID] AS [StudentID], 
    [Extent1].[StudentID] AS [StudentID1], 
    [Extent1].[Title] AS [Title], 
    [Extent1].[FullName] AS [FullName], 
    [Extent1].[Qualifications] AS [Qualifications], 
    [Extent1].[Gender] AS [Gender], 
    [Join1].[StudentSpecializationID] AS [StudentSpecializationID], 
    [Join1].[StudentSpecializationID] AS [StudentSpecializationID1], 
    [Join1].[StudentSpecializationID] AS [StudentSpecializationID2], 
    [Join1].[Name] AS [Name], 
    CAST(NULL AS int) AS [C2], 
    CAST(NULL AS int) AS [C3], 
    CAST(NULL AS int) AS [C4], 
    CAST(NULL AS varchar(1)) AS [C5]
    FROM  [dbo].[Student] AS [Extent1]
    LEFT OUTER JOIN  (SELECT [Extent2].[StudentSpecializationID] AS [StudentSpecializationID], [Extent2].[StudentID] AS [StudentID], [Extent3].[Name] AS [Name]
        FROM  [dbo].[StudentSpecialization] AS [Extent2]
        INNER JOIN [dbo].[Specialization] AS [Extent3] ON [Extent2].[SpecializationID] = [Extent3].[SpecializationID] ) AS [Join1] ON [Extent1].[StudentID] = [Join1].[StudentID]
UNION ALL
    SELECT 
    2 AS [C1], 
    [Extent4].[StudentID] AS [StudentID], 
    [Extent4].[StudentID] AS [StudentID1], 
    [Extent4].[Title] AS [Title], 
    [Extent4].[FullName] AS [FullName], 
    [Extent4].[Qualifications] AS [Qualifications], 
    [Extent4].[Gender] AS [Gender], 
    CAST(NULL AS int) AS [C2], 
    CAST(NULL AS int) AS [C3], 
    CAST(NULL AS int) AS [C4], 
    CAST(NULL AS varchar(1)) AS [C5], 
    [Join3].[StudentSubSpecializationID] AS [StudentSubSpecializationID], 
    [Join3].[StudentSubSpecializationID] AS [StudentSubSpecializationID1], 
    [Join3].[StudentSubSpecializationID] AS [StudentSubSpecializationID2], 
    [Join3].[Name] AS [Name]
    FROM  [dbo].[Student] AS [Extent4]
    INNER JOIN  (SELECT [Extent5].[StudentSubSpecializationID] AS [StudentSubSpecializationID], [Extent5].[StudentID] AS [StudentID], [Extent6].[Name] AS [Name]
        FROM  [dbo].[StudentSubSpecialization] AS [Extent5]
        INNER JOIN [dbo].[SubSpecialization] AS [Extent6] ON [Extent5].[SubSpecializationID] = [Extent6].[SubSpecializationID] ) AS [Join3] ON [Extent4].[StudentID] = [Join3].[StudentID]) AS [UnionAll1]
ORDER BY [UnionAll1].[StudentID1] ASC, [UnionAll1].[C1] ASC}

我不确定为什么在这里使用UNION。也许我使用投影很差。虽然我注意到L2E语句中包含两个或更多个投影,但UNIONS会出现在SQL中。

我尝试通过删除投影来尝试另一个方向,但未成功尝试使用Joins,Froms ......似乎无法让相关的子实体返回。

出于性能原因,我不能使用Include作为我使用我的摘要对象。

我还在质疑我现在是否正确地解决了这个问题,即我是否正在朝着返回嵌套相关(子)实体的方向前进?!?!也许我应该回到平坦的结果,例如学生,校园,专业化......对象都在同一级别,即删除层次结构。

问题

如果我使用T-SQL构建它,我将使用INNER& LEFT OUTER JOIN返回相关的子嵌套实体并过滤学生。这就是我尝试使用Linq to Entities实现的目标。我怎样才能做到这一点?例如。使用连接,投影或其他...(没有UNIONs和Cast(NULL)s ...

感谢任何帮助,即使它只是指向正确的方向,因为我真的被困在这里。感谢。

1 个答案:

答案 0 :(得分:0)

查询是否表现不佳?如果没有,请不要担心生成的sql。事实上,使用union all可能是实现这一目标的最佳方式。使用多个联接创建一个非常复杂的查询可能比结合union all

的多个简单查询慢