简体   繁体   English

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

[英]How do I query many-to-many mapping in EF4?

I have a pretty simple problem with a not-so-obvious solution. 对于一个不太明显的解决方案,我有一个非常简单的问题。 I have a relational mapping in my database between Users and Roles, and each user can be mapped to one or more roles. 我的数据库中有一个用户和角色之间的关系映射,每个用户都可以映射到一个或多个角色。 So the mapping is like so: 因此映射如下:

User < 1:n > UserRole < n:1 > Role 用户<1:n> UserRole <n:1>角色

In my generated EF4 POCOs, User and Role each have an ICollection of the other: 在我生成的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
}

Now, I've implemented the IoC, UoW, and repository patterns illustrated in this article , which uses an ObjectSet to fetch/persist the data via repositories. 现在,我已经实现了本文中说明的IoC,UoW和存储库模式, 模式使用ObjectSet通过存储库获取/持久化数据。

My question is, how do I implement this : 我的问题是, 如何实现这一点

public bool UserIsInRole(int userId, int roleId)

I have tried the following: 我尝试了以下方法:

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

But it fails with: 但是它失败了:

Unable to create a constant value of type 'Data.Models.Role'. 无法创建类型为“ Data.Models.Role”的常量值。 Only primitive types ('such as Int32, String, and Guid') are supported in this context. 在这种情况下,仅支持基本类型(例如Int32,String和Guid)。

Plus, it's not a very elegant implementation as it's having to hit the database twice. 另外,这不是一个非常优雅的实现,因为它必须两次访问数据库。

I was looking for something like this: 我一直在寻找这样的东西:

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

But ICollection doesn't support LINQ. 但是ICollection不支持LINQ。

How can I do this, and ideally, how can I do it with one LINQ expression and one trip to the database? 我该怎么做?理想情况下,如何使用一个LINQ表达式和一次数据库访问来完成呢?

Or, am I going about this completely wrong? 还是我要彻底解决这个问题?

Thanks in advance. 提前致谢。

Solved: Thanks to all who posted. 解决:感谢所有发布者。 All gave an acceptable answer. 所有人都给出了可接受的答案。 I accepted the one that was the most elegant. 我接受了最优雅的那种。

There is a more concise way to do it: 有一种更简洁的方法:

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

If I understand correctly you are trying to select all of the users in a specific role. 如果我理解正确,则您正在尝试选择具有特定角色的所有用户。

If that is the case then: 如果是这样,那么:

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;
}

You still have to hit the database twice but both of the queries should be pretty small. 您仍然必须两次访问数据库,但是两个查询都应该很小。


Since you say, in comments, that you already have the user that you want to use the above method should still work. 既然您在注释中说过,已经有想要使用上述方法的用户仍然可以使用。 I was about to write something to explain how you could do it using the repository pattern that is mentioned in the article but at the surface it isn't function any differently than using a context would, at least for querying. 我将要写一些东西来解释如何使用本文中提到的存储库模式来实现它,但从表面上看,它的功能与使用上下文没有什么不同,至少对于查询而言。

Since you are passing in a the User.Id as userId and not a complete User you still need to query for the appropriate user. 由于您要传递User.Id作为userId而不是完整的User您仍然需要查询适当的用户。

Now we can shorten the query some with 现在我们可以通过以下方式缩短查询时间:

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

Or Alternatively 或者

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

Try this: 尝试这个:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM