看起来Linq to Entities不支持Aggregate
方法。我需要将这个更大表达式的.Select(a => a.Permissions).Aggregate((a, b) => a | b)
部分重写为Linq to Entities理解的内容。有可能吗?
也许我应该更好地解释一下我在做什么。我需要根据这些组织者的用户权限从数据库中获取组织者的集合。权限存储为位标志,并且是以下内容的组合:
所以我有一个带有以下签名的方法
public IQueryable<Organizer> GetOrganizers(Person person, OrganizerPermissions requiredPermissions)
并且里面有一个像这样的代码
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);
简化它是这样的:
organizers = organizers.Where(o => ((
DefaultOrganizerPermissions |
OwnerOrganizerPermissions |
UserPermisions |
RolePermissions
) & requiredPermissions) == requiredPermissions);
问题是用户可以是多个角色的成员,因此RolePermissions实际上是多个权限,我需要使用按位OR将其展平。但是,如果不支持Aggregate怎么办?
答案 0 :(得分:1)
如果数据量不是非常大,您可以考虑在.ToList()
语句之前调用Select(...)
以将数据读入内存,然后执行聚合作为Linq to Objects
答案 1 :(得分:0)
如果权限可以为空,则可能需要插入
a.Permissions.GetValueOrDefault()
所以查询应该是
.Select(a =&gt; a.Permissions.GetValueOrDefault())。Aggregate((a,b)=&gt; a | b)
此外,如果EF提供程序不支持对SQL的聚合转换(此部分是提供程序特定的,因此它可以与一个DBMS一起使用但不能与不同的DBMS一起使用),则需要使用ToList()实现查询(如建议的那样) @sjager)。
修改强>
问题是EF提供程序不支持将聚合转换为SQL。
我不是SQL Server专家,无论如何你应该找到一个聚合函数(如SUM或AVG),它可以满足您的需要(按位OR)。在MySQL中是BIT_OR()。
如果它不存在则GAME OVER
如果存在,您可以查看SQL提供程序的SQL提供程序的源代码,并查看LINQ函数是否被翻译成该问题或提出另一个问题 -
答案 2 :(得分:0)
令人惊讶的是,我昨天遇到了完全相同的情况。 所以,正如@bubi所说,如果没有SQL服务器正确的聚合函数,那么就不可能。
我解决这个问题的方法是 - 为每个角色创建一堆OR表达式组,每个组都与用户角色进行比较。之后,将所有“OR表达式组”与AND谓词连接。
E.g。如果用户具有0011枚举值,则需要为0001和0010标志创建OR谓词。 0001标志“OR组”看起来像
x=> x.Equals(0001) || x.Equals(0011) || x.Equals(0101)| || ..)
但绝对不推荐。