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 キャッシュを作成することですが、キャッシュは常に私にとって最後の手段です (特にあなたが考える必要があるように)権限が変更された場合はクリアします)。

更新:Any Marcinの提案どおりに使用しますが、高速ではありません...

更新 2:IsAllowedをマッピング テーブルに移動し、 1 つだけを使用するようにクエリを調整しました...

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 サーバーは、検索に使用している UserName および PermissionKey フィールドにインデックスを作成するため、より高速になる場合があります。これはパーミッション システムであるため、これらのテーブルへの挿入はそれほど頻繁ではなく (インデックス付きビューでは挿入が少し遅くなる可能性があります)、より頻繁に読み取りを行っていると想定しています。

このクエリを 2 回目に実行するときも、EF キャッシュが原因で高速になるとは限りませんが、代わりに SQL サーバー キャッシュが原因である可能性があります。確かではありませんが、試してみる価値があるかもしれません。

于 2013-03-17T19:01:17.313 に答える