【问题标题】:linq to sql optimized a group with multiple joinslinq to sql 优化了具有多个连接的组
【发布时间】:2010-12-20 22:31:27
【问题描述】:

我需要帮助生成更高效的 LINQ 查询:

Table: Positions
-PositionID
-Name

Table: Person
-PersonID
-Name, etc...

Table: PersonPosition
-PersonID
-PositionID

我需要一个结果集,将分配给每个职位的人员分组:

PositionID  Person
1           John
            Bob
            Frank

2           Bill
            Tom
            Frank, etc...

我的第一个想法是这个 LINQ 查询:

from perspos in PersonPositions
join pers in Persons            on perspos.PersonID equals pers.PersonID 
group pers by perspos.PositionID into groups
select new {groups.Key, groups}

效果很好,但会产生以下 SQL:

SELECT [t0].[PositionID] AS [Key]
FROM [PersonPosition] AS [t0]
INNER JOIN [Person] AS [t1] ON [t0].[PersonID] = [t1].[PersonID]
GROUP BY [t0].[PositionID]
GO

-- Region Parameters
DECLARE @x1 Int = 3
-- EndRegion
SELECT [t1].[PersonID], [t1].[UserID], [t1].[Firstname], [t1].[Lastname], [t1].[Email], [t1].[Phone], [t1].[Mobile], [t1].[Comment], [t1].[Permissions]
FROM [PersonPosition] AS [t0]
INNER JOIN [Person] AS [t1] ON [t0].[PersonID] = [t1].[PersonID]
WHERE @x1 = [t0].[PositionID]
GO

-- Region Parameters
DECLARE @x1 Int = 4
-- EndRegion
SELECT [t1].[PersonID], [t1].[UserID], [t1].[Firstname], [t1].[Lastname], [t1].[Email], [t1].[Phone], [t1].[Mobile], [t1].[Comment], [t1].[Permissions]
FROM [PersonPosition] AS [t0]
INNER JOIN [Person] AS [t1] ON [t0].[PersonID] = [t1].[PersonID]
WHERE @x1 = [t0].[PositionID]
GO

-- Region Parameters
DECLARE @x1 Int = 5
-- EndRegion
SELECT [t1].[PersonID], [t1].[UserID], [t1].[Firstname], [t1].[Lastname], [t1].[Email], [t1].[Phone], [t1].[Mobile], [t1].[Comment], [t1].[Permissions]
FROM [PersonPosition] AS [t0]
INNER JOIN [Person] AS [t1] ON [t0].[PersonID] = [t1].[PersonID]
WHERE @x1 = [t0].[PositionID]
GO

on and on...

是否有更好的 LINQ 查询可以转换为更高效的 SQL 语句?

【问题讨论】:

    标签: c# linq-to-sql group-by


    【解决方案1】:

    您应该已经在您的数据库中以及您的 dbml 中定义了关系。

    避免在不必要时进行连接;他们真的很乏味。让 LINQ-to-SQL 为您完成这项工作。像这样的东西应该可以工作:

    var data = context.PersonPositions
        .Select(pos => new { pos.PositionID, pos.Person });
    return data.GroupBy(pos => pos.PositionID);
    

    return context.Positions.Select(pos => 
        new { pos, pos.PersonPositions.Select(pp => pp.Person).ToList() }).ToList();
    

    【讨论】:

    • 我有一个来自 Person -> PersonPosition 的一对多关系设置,但不是相反。在添加该关系时遇到问题,我得到“表 PersonPosition 中的列与任何现有的主键或唯一约束不匹配”。我不能将 PersonPosition 的 PersonID 设为 PK 或唯一索引,因为它是我在 Person-PersonPosition-Position 中的多对多关系的中间体,因此会有多个具有相同 PersonID 的记录
    • PersonPosition 表上是否有主键?您可以创建代理 PK (PersonPositionId) 或将 PersonId 和 PositionId 组合在一起,但您需要某种主键以供 LINQ-to-SQL 处理。
    • 谢谢。是的,我在 PersonPositions 表上有一个复合主键 (PersonID, PositionID),但仍然出现同样的错误。我在两个表中都允许 PersonID 为空,这会导致它吗?
    • 好吧,这可能会导致某些事情 - SQL 不允许您拥有可为空的 PK,无论是单列还是复合列,所以我不知道!检查 PK 是否仍在表格中,并且它们显示在 dbml 设计器中。列在数据库中应该是不可为空的,并且 dbml 也应该反映这一点(在属性查看器中)
    【解决方案2】:

    我很确定您只需加入表格并选择结果,然后调用 .AsEnumerable(),然后进行分组:

    (from perspos in PersonPositions
     join pers in Persons
     on perspos.PersonID equals pers.PersonID
     select new { perspos.PositionID, Person = pers })
    .AsEnumerable().GroupBy(p => p.PositionID, p => p.Person);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-05
      • 1970-01-01
      • 2018-08-21
      • 2010-09-09
      相关资源
      最近更新 更多