質問: サブクラス化によってデフォルトのアイデンティティを拡張する方法について説明します。説明したとおりにコードをセットアップしましたが、機能しますが、ユーザーの役割に応じて異なる属性があるため、さらに拡張したいと思います。たとえば、ApplicationUserはお気に入りを持つことができますが、拡張されたApplicationUserには要素があります。 ApplicationUserのサブクラスをさらに作成したいと思います。それは良い考えですか? モデルはElementです。 ApplicationUserには要素のセットがあり、それらをお気に入りに追加できます。 ExtendedApplicationUserはApplicationUserを継承し、ApplicationUserがお気に入りにできるElementのインスタンスを追加できます。 **私は何をすべきか?** 1. ApplicationUserとExtendedApplicationUserのロールを作成し、ApplicationUserで両方のセットを宣言しますが、サブクラスはありません。 2. または、各セットを各クラスに入れてApplicationUserをサブクラス化しますか?私が最初に考えたのはApplicationUserをサブクラス化することですが、代わりにロールを使用する方が良いアプローチかどうかわかりません。 最後の質問、ApplicationUserエンティティでセットを宣言するにはどうすればよいですか? HashSetまたはDbSetを使用しますか?
回答: はい、一般的に、継承はこれをモデル化する正しい方法です。 `IdentityUser`から継承する唯一のクラスが必要です。これがベース`ApplicationUser`なります。次に、他のタイプのユーザーが`ApplicationUser`から継承し`ApplicationUser` 。 とはいえ、EF Coreの継承の処理には、 *多くの*要望が*残さ*れています。特に、単一テーブル継承とも呼ばれるTPH(階層ごとのテーブル)のみをサポートします。つまり、何をするかに関係なく、ユーザーテーブルは1つだけになり、すべてのユーザータイプのすべての小道具がその1つのテーブルに存在する必要があります。実際には、他のサブクラスが値を提供できず、挿入が失敗するため、サブクラスにnull不可プロパティを設定できないことを意味します。ただし、ビューモデルを使用し、代わりに必要なものとそうでないものにビジネスルールを適用することで、これをほぼ軽減できます。 DBレベルでの検証は行われませんが、フォームなどからの入力は常に検証されます。 テーブルごとのタイプ(TPT)やテーブルごとのコンクリートタイプ(TPC)などのより適切なデータベースモデリング戦略を使用できないことを考えると、上記に言及する価値があります。 。特定のユーザータイプに対して、一部のプロパティセットのみを変更できるようにコードで強制する必要がない限り、単一のユーザークラスに固執することができます。複数のユーザータイプを用意するのは簡単なことではないので、特に必要がない限り、シンプルにするための議論があります。 特に、注意しないとユーザーの入力を台無しにするのは簡単です。単一テーブルの継承は、保存されている実際の型を保持する識別子列を追加することにより機能します。つまり、 `ApplicationUser`を保存すると、値は「ApplicationUser」になり、 `ExtendedApplicationUser`を保存すると、値は「ExtendedApplicationUser」になります。 EFはこの値を使用して、インスタンス化するタイプを決定します。難しいのは`UserManager`です。保存される型は、 `CreateAsync`などのメソッドに渡されるものではなく、汎用の型`CreateAsync`によって決まります。たとえば、 `ExtendedApplicationUser`を新規作成し、 `UserManager`インスタンスを介して保存すると、 `ApplicationUser`にアップキャストされて保存され、「ApplicationUser」がディスクリミネーター列に書き込まれます。 `ExtendedApplicationUser`する必要がある場合は、 `UserManager`インスタンスが必要です。また、特定のタイプのユーザーを操作するための複数のユーザーマネージャーが必要になる場合があります。そのため、適切なシナリオに対して適切なユーザーマネージャーを使用していることに注意する必要があります。 最後の質問では、答えはどちらでもありません。コレクションプロパティは、 `ICollection`または`List`いずれかでなければなりません。 `HashSet`は、プロパティに書き込むときに`ICollection`を満たすために使用できますが、そのように入力しないでください。 `DbSet`はコンテキスト専用です。