如何优化这个LINQ到EF / Sql查询(多对多关系)?

时间:2013-03-17 17:43:39

标签: c# sql linq entity-framework

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

enter image description here

目前我遵循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将实体缓存(第一次15-20ms)后大约需要1-2ms。这不是很慢,但是可以查询很多(例如,如果允许用户看到该项目,菜单系统会检查每个项目)我在问是否有更快的可能性?

我目前唯一能想到的就是创建一个User< - >权限缓存,以便在第一次调用后完全摆脱查询,但缓存始终是我的最后选择(特别是当你如果权限改变aso,则考虑清除它。)。

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

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

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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服务器将在您用于搜索的UserName和PermissionKey字段上创建索引。由于这是一个权限系统,我假设您不会经常插入这些表(索引视图可能会减慢插入速度)但是您更频繁地从中读取它。

第二次关闭此查询也可能因为EF缓存而更快,但可能是因为SQL服务器缓存。不确定,但可能值得尝试。