如何查询EF4中的多对多映射?

时间:2011-03-08 04:52:47

标签: linq entity-framework entity-framework-4 linq-to-entities poco

我有一个非常简单的问题,一个不那么明显的解决方案。我在用户和角色之间的数据库中有一个关系映射,每个用户都可以映射到一个或多个角色。因此映射就像这样:

  

用户< 1:n> UserRole< n:1>作用

在我生成的EF4 POCO中,用户和角色各自具有另一个的ICollection:

public class User 
{
    //Bunch of other properties/methods

    public virtual ICollection<Role> Roles
}

public class Role
{
    //Bunch of other properties/methods

    public virtual ICollection<User> Users
}

现在,我已经实现了this article中说明的IoC,UoW和存储库模式,它使用ObjectSet通过存储库获取/保存数据。

我的问题是,如何实施

public bool UserIsInRole(int userId, int roleId)

我尝试了以下内容:

public bool UserIsInRole(int userId, int roleId)
{
    Role role = _roleRepository.Single(r => r.Id == roleId);
    return _userRepository.SingleOrDefault(u => u.Roles.Contains(role)) != null;
}

但它失败了:

  

无法创建“Data.Models.Role”类型的常量值。在此上下文中仅支持原始类型(例如Int32,String和Guid')。

另外,它不是一个非常优雅的实现,因为它必须两次点击数据库。

我正在寻找这样的事情:

return _userRepository.SingleOrDefault(u => u.Roles.Where(r => r.Id = roleId));

但ICollection不支持LINQ。

我怎么能这样做,理想情况下,如何使用一个LINQ表达式和一次数据库之旅?

或者,我是否完全错了?

提前致谢。

解决: 感谢所有发布的人。所有人给出了可接受的答案我接受了最优雅的那个。

3 个答案:

答案 0 :(得分:3)

有一种更简洁的方法:

public bool UserIsInRole(int userId, int roleId)
{
    return _userRepository.
            Any(u => u.Id == userId && 
                     u.Roles.Any(r => r.Id == roleId));
}

答案 1 :(得分:1)

如果我理解正确,您将尝试选择特定角色中的所有用户。

如果是这样的话,那么:

public bool UserIsInRole(int userId, int roleId){
  var user = (from u in _userRepository where u.Id == userId select u).SingleOrDefult();
  if (user != null)
  {
     return (from r in user.Roles where r.Id = roleId select r).Any();
  }
  //you may not want to do this if you couldn't find the passed in user.
  return false;
}

你仍然需要两次点击数据库,但两个查询都应该很小。


由于您在评论中说您已经拥有要使用上述方法的用户,因此仍然可以使用。我正要写一些东西来解释如何使用文章中提到的存储库模式来解释它,但从表面来看,它与使用上下文的功能没有任何不同,至少对于查询而言。

由于您传递的User.IduserId而不是完整的User,因此您仍需要查询相应的用户。

现在我们可以使用

缩短查询
return _userReposity.Where(u => u.Id == userId)
                    .SelectMany(u => u.Roles)
                    .Where(r => r.id == roleId)
                    .SingleOrDefault() != null;

或者

return (from u in _userRepository
        from r in u.Roles
        Where u.Id == userId && r.Id = roleId
        Select r).Any();

答案 2 :(得分:1)

试试这个:

var result = _userRepository
              .Where(u => u.Id == userId)
              .SelectMany(u => u.Roles)
              .Where(r => r.Id == roleId)
              .SingleOrDefault();
return result != null;