Tengo una tabla de Usuario que almacena dos tipos de usuarios: Usuario o Grupo. Un usuario puede pertenecer a un grupo, lo que crea una tabla de referencia propia de la siguiente manera.
public class User { public Guid Id { get; set; } public string Name { get; set; } public string Email { get; set; } public string Type { get; set; } //Group || user public Guid GroupId { get; set; } public User Group { get; set; } public List<Role> Roles { get; set; } }Un usuario puede tener múltiples roles y viceversa, por lo que tengo las siguientes dos tablas.
public class Role { public Guid Id { get; set; } public string Name { get; set; } public List<User> Users { get; set; } } public class UserRole { public Guid Id { get; set; } public Guid UserId { get; set; } public User User { get; set; } public Guid RoleId { get; set; } public Role Role { get; set; } }Ahora necesito una consulta para obtener todos los roles que tiene un usuario. Estos roles pueden estar directamente asociados a un usuario o heredados de un grupo, donde un grupo puede heredarlos de otro grupo.
Soy nuevo en el núcleo del marco de la entidad y lo único que se me ocurrió fue seleccionar los roles directos usando
var userRoles = context.User.Where(u => u.Id == id).Include(x => x.Roles).Select(x => x.Roles).ToListAsync();
No soy capaz de abordar la situación de la herencia. Entonces, ¿cómo puedo obtener este resultado en una forma de nombre de rol y nombre de grupo heredado, preferiblemente en el núcleo de Entity Framework? Por favor ayuda.
Sugeriría soluciones recursivas, pero tal vez pueda causar pérdidas de rendimiento (si hay muchas autorreferencias).
La idea es que crees una función que obtenga el ID de usuario y devuelva una lista de roles, la lógica de la función es que agregamos los roles del usuario (relacionados con el ID de usuario en params) y agregamos los roles del grupo relacionado con este usuario (usamos el mismo método, este es el truco)
Para las funciones recursivas necesitamos una condición de parada, en mi ejemplo, hago cuando Group es nulo, necesita una condición de parada y asegurarse de que siempre sea seguro, de lo contrario, esto causará muchos problemas peligrosos.
public List<Roles> GetUserRoles(Guid userId) { var roles = new List<Roles>(); var user= context.User.FirstOrDefault(u => u.Id == id).Include(x => x.Roles); roles.AddRange(user.Roles); if (user.Group != null) { roles.AddRange(GetUserRoles(user.GroupId)); } return roles; }