I can do this very simply in SQL, but trying to learn how to do this in Linq using Entity Framework.
I have a User, a User can have multiple Groups, and a group can have multiple Permissions.
I would like to get all the permissions for a user.
I have the following DbSets in my DbContext
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Group> Groups { get; set; }
public virtual DbSet<Permission> Permissions { get; set; }
And there classes are like so
public class User : Entity, IUser<long>
{
public string UserName { get; set; }
public string PasswordHash { get; set; }
public User()
: base()
{
this.Groups = new HashSet<UserGroup>();
}
public virtual ICollection<UserGroup> Groups { get; set; }
}
public class Group : AuditableEntity
{
public Group() {
this.Permissions = new HashSet<GroupPermission>();
}
public string Name { get; set; }
public virtual ICollection<GroupPermission> Permissions { get; set; }
}
public class Permission
{
public string Name { get; set; }
public Permission()
{
}
}
To cope with the many to many relationships, i also have these classes
public class UserGroup
{
public long UserId { get; set; }
public long GroupId { get; set; }
public virtual User User { get; set; }
public virtual Group Group { get; set; }
}
public class GroupPermission
{
public long PermissionId { get; set; }
public long GroupId { get; set; }
public virtual Permission Permission { get; set; }
public virtual Group Group { get; set; }
}
Now in SQL i would simply do
SELECT Permission.*
FROM Permission
INNER JOIN PermissionGroup ON Permission.Id = PermissionGroup.PermissionId
INNER JOIN Group ON PermissionGroup.GroupId = Group.Id
INNER JOIN UserGroup ON Group.Id = UserGroup.GroupId
WHERE UserGroup.UserId = @UserId
Can someone please tell me why i cant do this in LINQ? Well i know i can, but i cannot figure out how.
EDIT
context.PermissionGroup and context.UserGroup are not DbSets in my context.
List<Permission> result;
using(DataContext context = new DataContext())
{
result = (from permission in context.Permissions
join permissionGroup in context.PermissionGroup on permission.Id equals permissionGroup.Id
join g in context.Groups on permissionGroup.GroupId equals g.Id
join userGroup in context.UserGroup on g.Id equals userGroup.GroupId
where userGroup.UserId == user.Id
select permission).ToList();
}
use this
var linqQuery=(from p in Permission
join pg in PermissionGroup on p.Id equals pg.Id
join g in Group on pg.GroupId equals g.Id
join ug in UserGroup on g.Id equals ug.GroupId
where ug.UserId == USERID
select p);
If you have your own DbContext
class where all your database tables are represented as DbSets
public partial class OwnContext: DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Group> Groups { get; set; }
public DbSet<Permission> Permissions { get; set; }
public DbSet<UserGroup> UserGroups { get; set; }
public DbSet<PermissionGroup> PermissionGroups { get; set; }
}
you have to create an instance of that class with a using statement and execute your query in the using statement .
List<Permission> result;
using(OwnContext context = new OwnContext())
{
result = (from permission in context.Permissions
join permissionGroup in context.PermissionGroups on permission.Id equals permissionGroup.Id
join group in context.Groups on permissionGroup.GroupId equals group.Id
join userGroup in context.UserGroups on group.Id equals userGroup.GroupId
where userGroup.UserId == user.Id
select permission).ToList();
}
Joining in SQL doesn't automatically mean that you should join in LINQ. Use navigation properties whenever possible. Your case becomes much simpler if you do that, and use SelectMany
for this:
from u in db.Users
select new {
u.UserName,
Permissions = u.Groups
.Select(ug => ug.Group)
.SelectMany(g => g.Permissions)
.Select(gp => gp.Permission
}
using (var context = new NombreDeEntityDataModel)
{
var query = from a in context.Permission
join b in context.PermissionGroup on a.id equals b.PermissionId
join c in context.Group on b.GroupId equals c.id
join d in context.UserGroup on c.id equals d.GroupId
where d.UserId = @UserId
select a;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.