4

我正在实现一个权限系统,其中用户在角色中,然后这个角色有权限,我正在考虑查询它们的最快方法:

在此处输入图像描述

目前我有以下 LINQ 查询:

var grant = db.Permissions.Any(p => p.Group == group && p.PermissionKey == permission
&& !p.Roles.Any(r => !r.IsAllowed && r.Role.Users.Any(u => u.UserName == user.Identity.Name)) 
&& p.Roles.Any(r => r.IsAllowed && r.Role.Users.Any(u => u.UserName == user.Identity.Name)));

return grant;

在 EF 缓存实体后,这大约需要 1-2 毫秒(第一次需要 15 到 20 毫秒)。这不是很慢,但是因为这可以查询很多(例如,如果允许用户查看该项目,菜单系统会检查每个项目)我问是否有更快的可能?

目前我唯一能想到的就是创建一个 User<->Permission 缓存以在第一次调用之后完全摆脱查询,但是缓存对我来说始终是最后的手段(尤其是当您想到如果权限也发生变化,则清除它。)。

更新:按照 Marcin 的建议使用Any,但速度并不快......

更新 2:我将 移动IsAllowed到映射表并调整查询以仅使用一个...

4

2 回答 2

4

您应该将每个Count() > 0语句更改为Any方法调用,例如:

r => r.Users
      .Count(u => u.UserName == user.Identity.Name) > 0

应替换为:

r => r.Users
      .Any(u => u.UserName == user.Identity.Name)
于 2013-03-17T17:52:21.517 回答
0

您是否尝试过在数据库中创建索引视图?

CREATE VIEW mySchema.UserRolePermission
WITH SCHEMABINDING
/* your SELECT goes here */
GO
CREATE UNIQUE CLUSTERED INDEX MyIndexName
ON mySchema.UserRolePermission (UserName, PermissionKey);
GO

然后,您的 LINQ2SQL 查询将改为从此视图中直接选择。它可能会更快,因为 SQL Server 将在您用于进行搜索的 UserName 和 PermissionKey 字段上创建索引。由于这是一个权限系统,我假设您不会经常插入这些表(索引视图可能会减慢插入速度),但您会更频繁地从中读取。

由于 EF 缓存,第二次触发此查询也可能不会更快,但可能是因为 SQL 服务器缓存。不确定,但可能值得一试。

于 2013-03-17T19:01:17.313 回答