简体   繁体   中英

Ef Core filtering included query using uow and repository

I started creating a role-based security system in my WinForm application so I began with Form navigation (Permission Navigation) and this is my entity's

public partial class User
{
    public User()
    {
        UsersToRoles = new HashSet<UsersToRole>();
    }
    
    public string Login { get; set; } = null!;
    public string PasswordUser { get; set; } = null!;
    public string? FullName { get; set; }
    public string? Email { get; set; }
    public int Id { get; set; }
    
    public virtual ICollection<UsersToRole> UsersToRoles { get; set; }
}
    
public partial class Role
{
    public Role()
    {
        UsersToRoles = new HashSet<UsersToRole>();
        PermissionNavigations = new HashSet<PermissionNavigation>();
    }
  
    public int Id { get; set; }
    public string Name { get; set; } = null!;
   
    public virtual ICollection<UsersToRole> UsersToRoles { get; set; }
    public virtual ICollection<PermissionNavigation> PermissionNavigations { get; set; }
}
    
public partial class UsersToRole
{
    public int Id { get; set; }
    public int IdUser { get; set; }
    public int IdRole { get; set; }
    
    public virtual Role IdRoleNavigation { get; set; } = null!;
    public virtual User IdUserNavigation { get; set; } = null!;
}
    
public partial class Navigation
{
    public Navigation()
    {
        PermissionNavigations = new HashSet<PermissionNavigation>();
    }
    
    public int Id { get; set; }
    public string Page { get; set; } = null!;
    public string Forms { get; set; } = null!;
   
    public virtual ICollection<PermissionNavigation> PermissionNavigations { get; set; }
}
    
public partial class PermissionNavigation
{
    public int Id { get; set; }
    public int IdRole { get; set; }
    public int IdNavigation { get; set; }
    
    public virtual Navigation IdNavigationNavigation { get; set; } = null!;
    public virtual Role IdRoleNavigation { get; set; } = null!;
}

This is my geniric GetAllIncluding method

public async Task<IEnumerable<T>> GetAllIncluding(params Expression<Func<T, object>>[] includeProperties)
{
    try
    {
         IQueryable<T> query = dbSet;
         foreach (Expression<Func<T, object>> includeProperty in includeProperties)
         {
             query = query.Include<T, object>(includeProperty);
         }
         return await query.ToListAsync();
    }
    catch (Exception ex)
    {
         throw new Exception($"{nameof(GetAllIncluding)} properties could not be included properly: {ex.Message}");
    }
}

And this is how I use it in my PermissionNavigationService

public async Task<IEnumerable<PermissionNavigationDto?>> 
    GetAllPermissionNavigationDetailsByUserAsync(int idUser)
{
    var permissionNavigation = await unitOfWork.PermissionNavigations.GetAllIncluding(
                        x => x.IdNavigationNavigation,
                        x => x.IdRoleNavigation,
                        x => x.IdRoleNavigation.UsersToRoles.Where(x=>x.IdUser== idUser));
    
    return mapper.Map<IEnumerable<PermissionNavigationDto?>>(permissionNavigation);
}

I know that this line of code only filtering UsersToRoles entity not PermissionNavigation entity

x => x.IdRoleNavigation.UsersToRoles.Where(x=>x.IdUser== idUser)

The question is: What can be done to get all Permission Navigation related to specific user

Update1
I am looking for something like this but in ef core

SELECT PermissionNavigation.[Id]
      ,PermissionNavigation.[IdRole]
      ,Roles.Name
      ,Navigation.Forms
      ,[IdNavigation]
      ,UsersToRoles.IdUser
    FROM [SIM].[dbo].[PermissionNavigation]
    INNER JOIN Roles on Roles.Id=IdRole
    INNER JOIN Navigation on Navigation.id=IdNavigation
    INNER JOIN UsersToRoles on UsersToRoles.IdRole=PermissionNavigation.[IdRole]
    WHERE UsersToRoles.IdUser=@IdUser

Update2
I appreciate all the help I received.
I decided to go this way:
When the user has successfully logged in, I catch the Id then I make a call to get all roles related to that user after that I make another call to get all permission navigation using role Id that I got earlier.

    List<PermissionNavigationDto> navigationDtos = new();
    var userRoles = await userToRoleService.GetUserRolesAsync(LoginUserDetails.Id);          
    foreach (var role in userRoles)
    {
        var navigation = await permissionNavigationService.GetPermissionNavigationByRoleIdAsync(role.IdRole);
        navigationDtos.AddRange(navigation);
    }

What you need is the SelectMany

//The userId concerned
int userId = 1;

//As an example, let's say you have your repository items below
List<User> users = new List<User>();
List<UsersToRole> userToRoles = new List<UsersToRole>();
List<Role> roles = new List<Role>();            

//if you have to retrieve user
User myUser = users.SingleOrDefault(x => x.Id == userId);

//get all roleIds this user (userId = 1) belongs to
List<int> roleIds = userToRoles.Where(x => x.IdUser == userId).Select(us => us.IdRole).ToList();

//get the role objects, then the PermissionNavigations and flatten it out with SelectMany
List<PermissionNavigation> permissionNavigations = roles.Where(us => roleIds.Contains(us.Id)).Select(us => us.PermissionNavigations).SelectMany(x => x).ToList();

I hope this helps.

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.

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