entity framework - propiedad - Enlace al reemplazo del método Agregado de Entidades
propiedad alt imagen (3)
Parece que Linq to Entities no admite el método Aggregate
. Necesito reescribir esto. .Select(a => a.Permissions).Aggregate((a, b) => a | b)
parte de una expresión más grande a algo que Linq to Entities entienda. ¿Es posible?
Tal vez debería darte una mejor explicación de lo que estoy haciendo. Necesito obtener una colección de Organizadores de la base de datos en función de los permisos de usuario para estos Organizadores. Los permisos se almacenan como indicadores de bits y son una combinación de los siguientes:
- DefaultOrganizerPermissions: cada organizador tiene algunos permisos predeterminados
- OwnerPermissions: si el usuario es el propietario del Organizador, tiene un permiso adicional
- UserPermisions: los usuarios se pueden asignar manualmente para tener algunos Permisos para el Organizador
- RolePermissions: los usuarios pueden ser miembros de roles y estos roles se pueden asignar para tener permisos adicionales para los organizadores.
Entonces tengo un método con la siguiente firma
public IQueryable<Organizer> GetOrganizers(Person person, OrganizerPermissions requiredPermissions)
y dentro de él hay un código como este
organizers = organizers.Where(o => ((
// Default permissions
DefaultOrganizerPermissions |
// Owner permissions
(o.OwnerId == person.Id ? OwnerOrganizerPermissions : 0) |
// Personal permissions
(o.AccessIdentifier.Accesses.FirstOrDefault(a => a.Accessor is PersonalAccessor && (a.Accessor as PersonalAccessor).PersonId == person.Id) != null ?
(OrganizerPermissions)o.AccessIdentifier.Accesses.FirstOrDefault(a => a.Accessor is PersonalAccessor && (a.Accessor as PersonalAccessor).PersonId == person.Id).Permissions : 0) |
// Role permissions
(o.AccessIdentifier.Accesses.Any(a => a.Accessor is RoleAccessor && (a.Accessor as RoleAccessor).Role.RoleMembers.Any(rm=>rm.PersonId == person.Id)) ?
(OrganizerPermissions)o.AccessIdentifier.Accesses.Where(a=> a.Accessor is RoleAccessor && (a.Accessor as RoleAccessor).Role.RoleMembers.Any(rm => rm.PersonId == person.Id)).Select(a=>a.Permissions).Aggregate((a, b) => a | b) : 0)
) & requiredPermissions) == requiredPermissions);
Simplificado es algo como esto:
organizers = organizers.Where(o => ((
DefaultOrganizerPermissions |
OwnerOrganizerPermissions |
UserPermisions |
RolePermissions
) & requiredPermissions) == requiredPermissions);
El problema es que el usuario puede ser miembro de varios Roles, por lo que los RolePermissions son en realidad permisos múltiples y necesito aplanarlo con OR a nivel de bit. ¿Pero cómo, si Aggregate no es compatible?
Si la cantidad de datos no es prohibitivamente grande, podría considerar llamar a .ToList()
antes de la instrucción Select(...)
para leer los datos en la memoria y luego realizar el agregado como Linq a los objetos
Si Permisos es nulo, probablemente necesites insertar
a.Permissions.GetValueOrDefault ()
por lo que la consulta debe ser
.Seleccione (a => a.Permissions.GetValueOrDefault ()). Aggregate ((a, b) => a | b)
Además, si el proveedor de EF no admite la traducción Agregada a SQL (esta parte es específica del proveedor para que pueda funcionar con un DBMS pero no con un DBMS diferente) necesita materializar la consulta con ToList () (como sugiere @sjager) .
EDITAR
El problema es que el proveedor de EF no admite la traducción agregada a SQL.
No soy un experto en SQL Server; de todos modos, debería encontrar una función agregada (como SUM o AVG) que haga lo que necesita (OR a nivel de bits). En MySQL es BIT_OR ().
Si no existe, entonces GAME OVER
Si existe, puede ver el código fuente del proveedor EF para SQL Server y ver qué función LINQ se traduce en eso o hacer otra pregunta-
Sorprendentemente, ayer corrí a la misma situación. Entonces, como @bubi declaró, sin una función de agregación propia de SQL Server no es posible .
La forma en que lo he solucionado es: crear un grupo de grupos de expresiones OR para cada rol, cada uno de ellos teniendo una comparación con un rol de usuario. Después de eso, conecte todos los "grupos de expresiones OR" con el predicado AND.
Por ejemplo, si el usuario tiene un valor de enumeración 0011, deberá crear predicados O para los indicadores 0001 y 0010. 0001 bandera "OR grupo" se vería como
x=> x.Equals(0001) || x.Equals(0011) || x.Equals(0101)| || ..)
Pero definitivamente no es recomendable.