如何在 EF4 中查询多对多映射?
我有一个非常简单的问题,但解决方案并不那么明显。我的数据库中有一个用户和角色之间的关系映射,每个用户可以映射到一个或多个角色。所以映射就像这样:
用户< 1:n>用户角色 < 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
}
现在,我已经实现了 本文,它使用 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 表达式和一次数据库访问来实现这一点?
或者,我的做法完全错误吗?
提前致谢。
已解决: 感谢所有发帖的人。大家都给出了可以接受的答案。我接受了最优雅的那一个。
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
In my generated EF4 POCOs, User and Role each have an ICollection of the other:
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.
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'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
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.
How can I do this, and ideally, how can I do it with one LINQ expression and one trip to the database?
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
试试这个:
Try this:
如果我理解正确的话,您正在尝试选择特定角色的所有用户。
如果是这种情况,那么:
您仍然需要访问数据库两次,但两次查询都应该非常小。
既然您在评论中说您已经拥有要使用上述方法的用户,那么上述方法应该仍然有效。我本来打算写一些东西来解释如何使用文章中提到的存储库模式来做到这一点,但从表面上看,它的功能与使用上下文没有任何不同,至少对于查询来说是这样。
由于您将
User.Id
作为userId
传递,而不是完整的User
,因此您仍然需要查询适当的用户。缩短一些查询
现在我们可以使用Or Alternative 来
If I understand correctly you are trying to select all of the users in a specific role.
If that is the case then:
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
asuserId
and not a completeUser
you still need to query for the appropriate user.Now we can shorten the query some with
Or Alternatively
有一种更简洁的方法可以做到这一点:
There is a more concise way to do it: