所以你有Users
和UserRoles
。Users 和 UserRoles 之间存在一对多的关系:每个 User 都有零个或多个 UserRoles;每个 UserRole 只属于一个 User,即外键 UserId 所指的 User。
您也有一个用户名,并且您希望所有用户都有这个名称,每个用户都有自己的用户角色。
注意:您没有说 UserName 是唯一的,所以可以是,在之后Where
您仍然有几个用户名为“Will Smith”的用户。
简短的回答
string userName = "Will Smith";
var result = dbContext.Users
.Where(user => user.UserName == userName)
.Join(dbContext.UserRoles,
user => user.Id, // from each User take the Id
userRole => userRole.UserId, // from each UserRole take the foreign key
(user, userRole) => userRole);
或者反过来:从 UserRoles 开始,只保留那些具有用户名的用户角色:
dbContext.UserRoles.Where (userRole =>
dbContext.Users
.Where(user => user.Id == userRole.UserId // get the User of this Role
&& user.UserName == userName) // check the name of this User
.Any() );
有改进的余地
如果用户 [10] 有 20 个用户角色,那么用户 [10] 的每个用户角色都将有一个值为 10 的外键。您将传输此值 20 次。
如果有多个“Will Smith”,您将拥有一个大序列,其中所有“Will Smith”的所有 UserRole 随机混合。
您的解决方案将导致:
UserId UserRole
10 Administator,
10 User
25 Backup
10 Backup
18 User
25 User
对用户进行分组不是更有效吗,所以你有类似的东西:
UserId UserRoles
10 { Administator, User, Backup }
18 { User }
25 { User, Backup }
22 <no UserRoles yet>
注意:结果略有不同:您还获得了还没有角色的用户。
每当您有带有零个或多个子项的项目时,例如带有学生的学校、带有订单的客户或带有 UserRoles 的用户,请考虑使用Queryable.GroupJoin的重载之一。
大多数时候,我使用带有参数 resultSelector 的重载。通过这种方式,您可以准确指定所需的属性以及格式:
var usersWithTheirUserRoles = dbContext.Users
// keep only the users with a specific UserName
.Where(user => user.UserName == userName)
// fetch some properties of the remaining users and their UserRoles
.GroupJoin(dbContext.UserRoles,
user => user.Id, // from each User take the Id
userRole => userRole.UserId, // from each UserRole take the foreign key
// parameter resultSelector: take each user, with its zero or more userRoles
// to make one new:
(user, userRolesOfThisUser) => new
{
// Select only the user parameters that you plan to use:
Id = user.Id,
Address = user.Address,
...
// select the zero or more user roles of this user
UserRoles = userRolesOfThisUser.Select(userRole => new
{
// Select only the properties that you plan to use
Id = userRole.Id,
Description = userRole.Description,
...
// not needed, you've already got the value:
// UserId = userRole.UserId,
})
.ToList(),
});
好处:
- 您还可以获得还没有 UserRoles 的用户(在您的原始要求中没有问题)
- 效率:用户的每个属性只发送一次。内连接或左外连接将一遍又一遍地发送用户的相同属性
- 效率:您只传输您真正需要的属性
- 您可以偏离原始表格。如果你想省略 UserRoles,或者计算一些属性,
UserRoleCount
你可以这样做。这使得将来更改数据库表变得更容易,而无需更改此查询