4

この問題に対処する方法を見つけようとしています:

多対多の関係を持つ 3 つのテーブルがあります。

Users *-* Roles *-* Permissions

ORM を使用してそれらからデータを取得します。

私のビジネス レイヤーのメソッドは、パーミッションごとにユーザーを返す必要があるため、次のクラスのオブジェクトを返します。

public class UsersPerPermission
{
    public User[] {get;set;}
    public Permission {get;set;}
}

ただし、このクラスはリポジトリ内のどのテーブルにもマップされません。既存のテーブルから生成したものです。このクラスはどこに住むべきですか?

言い換えると:

  • 私は持っているべきIRepository.GetUsersPerPermission()ですか?そして、そのクラスはリポジトリに存在する必要があります。

  • それとも持っているべきIBusinessLayer.GetUsersPerPermission()ですか?そして、リポジトリで CRUD メソッドを呼び出す必要がありますか?

リポジトリはCRUD操作をテーブルに公開するだけなので、ビジネスレイヤーにのみ配置することは理にかなっています...しかし、ビジネスレイヤーからこの操作を実行するには、データを取得するためにいくつかの独立したクエリを実行する必要があります「UserPerPermission」クラスを作成します。逆にリポジトリに入れておけば、グルーピングを使えば一発で情報を取得できます。

ありがとう!

PS: この中間オブジェクトの名前は? 「変換」?

4

3 に答える 3

4

DDDでは、ほとんどのエンティティと値オブジェクトは、ユビキタス言語の一部である識別されたドメインの概念に対応している必要があります。私は通常、多対多の関係と人工的な関連オブジェクトを可能な限り制限しようとします。エリック・エバンスは、彼の本でそれを可能にするいくつかのテクニックを説明しています。アソシエーションオブジェクトを作成する必要がある場合、ドメインに関して意味のある名前を付ける必要があります。基本的に、名前を付けることはありませんClass1ToClass2。あなたのシナリオでは、あなたのオブジェクト以来、それはさらに人工的です:

  • 元のモデルに(間接的に)すでに存在する関連付けを冗長にモデル化します。
  • 特定のビジネスコンセプトを反映していない名前が付いています。

この種のオブジェクトは、画面に表示されているもの(DTO)を正確に含む構造を持つと便利なため、プレゼンテーション層またはアプリケーション層にいる場合は役に立たないことに注意してください。しかし、私はここでドメインレイヤーについて話しているので、そのような複合オブジェクトはないはずです。

UsersPerPermissionですから、そもそもクラスを作成することはしません。必要なのがユーザーのリストであり、Userが集約ルートである場合は、でGetUsersByPermission()メソッドを作成するだけUserRepositoryです。アプリケーションのユースケース(1つのアクセス許可の詳細とそのアクセス許可を持つユーザーのリストを表示する画面)に一致する場合、アプリケーションGetUsersByPermission()サービスにもメソッドを含めることができないという意味ではありません。

于 2012-09-02T08:28:29.540 に答える
0

同様のコンテキストで、ドメインサービスでクエリメソッドを使用しました。

IEnumerable<KeyValuePair<PermissionName, IEnumerable<Username>>>

KeyValuePair <>を使用することで、ドメインモデルを人為的な概念(UsersPerPermitionなど)で汚染することを回避しました。さらに、そのような構造は不変です。私のコンテキストでは、エンティティが他のエンティティと結合されていなかったため、リポジトリでクエリメソッドを使用しませんでした。したがって、どのリポジトリでも問題ではありませんでした。

ただし、このソリューションは、エンティティの識別子を正しくモデル化した場合にのみGUIに役立ちます(この例では、パーミッションとユーザーの両方がエンティティです)。実際、それらがユーザーが理解するユビキタス言語に属する共有識別子である場合、それ以上の説明がなくても十分です。

それ以外の場合は、GUIに役立つDTOを構築しているだけです。ドメインに属していないため、機能する最も単純なものを使用する必要があります(ADO.NETクエリ?さらに単純なもの?)。実際、私自身のシナリオでは、GUIとドメインの両方がそのようなサービスを使用していました(GUIは詳細のプレビューを示しています)。

一般に、ドメインモデルは、ドメインエキスパートの言語を反映し、制限されたコンテキストに関連する知識をキャプチャする必要があります。それ以外はすべてドメイン外にある必要があります(ただし、ほとんどの場合、ドメインの値オブジェクトで表すことができます)。

于 2012-09-09T11:03:18.600 に答える
0

単一のユース ケースをサポートするためにドメイン オブジェクト「UsersPerPermission」を導入する必要がないという guillaume31 に同意します。

既存のドメイン クラス "User"、"Role"、および "Permission" を使用してユース ケースを実装するには、2 つの方法があります。


解決策 1:

あなたが持っていると仮定します: パーミッション --> ロール --> ユーザー

矢印はナビゲーション可能性を示します。パーミッションはロールのリストに関連付けられ、ロールはユーザーのリストに関連付けられます。

GetPermittedUsers() : List<User>簡単に実装できるメソッドを Permission クラスに追加します。

UI ロジックは、PermissionRepository の GetPermissions() を呼び出してから、各アクセス許可で GetPermittedUsers() を呼び出します。

hibernate(Nhibernate) のような ORM フレームワークを使用し、多対多の関係を正しく定義していると仮定します。Role と User の Permission からの一括読み込みを定義すると、ORM は Permission、Role、および User テーブルを結合するクエリを生成し、すべてを一度に読み込みます。ロールとユーザーの遅延読み込みを定義すると、PermissionRepository を呼び出すときに 1 つのクエリでアクセス許可のリストを読み込み、関連するすべてのロールとユーザーを別のクエリで読み込みます。すべてが最大 3 つのクエリでデータベースからロードされます。これは 1+n 問題と呼ばれ、ほとんどの ORM が適切に処理します。


解決策 2:

ユーザー --> ロール --> 権限があると仮定します。

矢印はナビゲーション可能性を示します。ユーザーにはロールのリストがあります。ロールには権限のリストがあります。

getUsersByPermissions(List<long> permissionIds) : List<Users>UserRepository に追加しgetPermissions() : List<Permission>、User クラスに追加します。

UserRepository の実装では、User、Role、および Permission テーブルを 1 つのクエリに結合し、すべてを一度にロードする必要があります。繰り返しますが、ほとんどの ORM はそれを正しく処理します。

ユーザーのリストを取得したら、Map<Permission, List<User>>非常に簡単に構築するメソッドを作成できます。


正直なところ、私は解決策が好きです。ユーザーのリストをアクセス許可とユーザーのマップに変換するための複雑なメソッドを記述することは避けているため、このメソッドをどこに配置するかについて心配する必要はありません。ただし、ソリューション 1 では、既に別の方向にナビゲートできる場合、User、Role、および Permission クラス間に循環関係が作成される場合があります。循環的な関係を好まない人もいます。ユーザーケースが要求すれば、循環関係はいつか必要になるとしても許容できると思います。

于 2012-09-08T22:13:52.020 に答える