如何将此LINQ查询编写为单个查询?

时间:2011-10-19 18:30:49

标签: c# linq

考虑以下代码:

var query = from groupRole in CurrentItem.MEMGroupRoles 
            select groupRole.MEMRole;
this.AvailableRoles = this.allRoles.Except(query.AsEnumerable()).ToList();

在这段代码中,除了CurrentItem已经拥有的那些角色之外,我将使用allRoles。 2个问题:

  1. 它不起作用,因为我在对象上进行比较,而那些对象是不同的实例
  2. 我不喜欢2行,喜欢改进。
  3. 这是关于我现在真正需要做的伪代码:

    var queryIds = from groupRole in CurrentItem.MEMGroupRoles 
                   select groupRole.MEMRole.RoleId;
    this.AvailableRoles = this.allRoles.Except(where RoleId query.AsEnumerable()).ToList();
    

    如何编写这样的查询?

    编辑

    说明:

    1. allRoles包含MEMRole对象列表
    2. CurrentItem.MEMGroupRoles包含MEMGroupRole对象列表,每个MEMGroupRole包含MEMRole
    3. 我想选择allRoles里面的所有MEMRole对象,除了那些埋在CurrentItem里面的MEMRoles。第一个代码片段可以工作,但我需要通过MEMRole.RoleId将MEMRole与MEMRole进行比较,因为它是同一个数据库实体的不同实例。

3 个答案:

答案 0 :(得分:1)

如果角色对象使用角色ID识别它是有意义的,您可以覆盖Equals()GetHashCode()。如果不是这种情况,您可以创建一个实现IEqualityComparer<>的角色比较器类。 Except()将等式比较器作为第二个参数。

这是一个为角色ID创建查找并使用它来过滤角色的解决方案。但是,我确实认为上面的替代方案是解决问题的更好方法。

var lookup = CurrentItem.MEMGroupRoles
        .ToLookup(groupRole => groupRole.MEMRole.RoleId);
this.AvailableRoles = this.allRoles
        .Where(role => !lookup.Contains(role.RoleId))
        .ToList();

答案 1 :(得分:0)

按照您建议的方法:

var ids = CurrentItem.MEMGroupRoles.Select(g => g.MMERole.RoleId);
this.AvailableRoles = this.allRoles.Where(r => ids.All(i => i != r.RoleId));

或者(虽然我不会走那条路),如果你必须有单一查询,你可以追加两个角色集合(当前所有< / em>),按RoleId对它们进行分组,并选择只有一个成员的组:

this.AvailableRoles = CurrentItem.MEMGroupRoles
    .Select(g => g.MEMRole)
    .Concat(this.allRoles)
    .GroupBy(r => r.RoleId)
    .Where(g => g.Count() == 1)
    .Select(g => g.First());

这导致角色不在CurrentItem.MEMGroupRoles集合中。但再一次,它只是......对于运动:)

答案 2 :(得分:0)

这是LINQ to SQL吗?

如果是这样,请使用DataContext.Log属性查看传递给数据库的实际SQL,这可能有助于您诊断问题。