c# - C#クラスの設計-「プロジェクト」クラスの配置を検討すべき場所

c# asp.net .net class-design hierarchy

プロジェクト管理アプリケーションのクラスライブラリを作成しています。問題の支援のためにすべてのエンティティがどのように設定されているかについて簡単に説明します。

userは、登録時にplanにサブスクライブします。すべてのプランには、アカウントの検証に成功した後に使用できるmodules/applicationsが含まれています。 ProjectCompanyPlansは、クラスライブラリを作成しているモジュールであり、これらはユーザーライフサイクルのすべての段階で存在するモジュールです。ロールは、ユーザーが実行できるかどうかを決定します。各企業(ユーザーごとに1つのみ)は多くのプロジェクトを収容でき、各プロジェクトにはリソースを持つ専任のプロジェクトリーダーがいます。プロジェクトリーダーは、より高いprivileges/Rolesを持つ別のユーザーです。どちらも私には問題ないと思われるので、ここで混乱する部分があります:クラス階層のうち、私は1または2に従う必要があります

1

User

  - Subscriptions ( List<> )

  - Projects ( List<> )
      - Client ( Client )
      - ProjectLead( User )
      - Resources(List<>)


2

Application

   - Projects ( List<> )

     - Client ( Client )
     - ProjectLead ( User )
     - Resources ( List<> )

User

  - GetProjects ( List <Project> )


混乱はほとんどこの時点で発生しません。クライアントは外部キーProjectIdを通じてプロジェクトに関連付けられます。したがって、Clientのクラスを作成している間、


クライアントが属するプロジェクトを示すには、クライアントクラス内にProject Classを作成するか、またはクライアントを
プロジェクトクラス。
答え
次のように、どのオブジェクトが別のオブジェクトと関係を持つべきか混乱していることを正しく理解していますか?

オプション1:ユーザーはプロジェクトを持っています(彼はリードです)
オプション2:プロジェクトにはユーザーがいます(これがリードです)

そしてそれ以上。

良いニュースは:あなたが選択する必要はありません。双方向の関係を記述できます。
これを実装するにはいくつかの方法があります。

外部キーについて話しているので、バックエンドデータベースを使用してオブジェクトを永続化していると思いますか?その場合、Entity Frameworkのようなオブジェクトリレーショナルデータベースマッパー(ORM)を使用できます。そうでない場合は、自分でいくつかの作業を行う必要があります。これは、個人的には避けたいことです;)

エンティティフレームワーク

最初にすべての関係を持つデータベースを作成し、次にエンティティフレームワークに対応するクラスを生成させます。これらすべてのクラスには双方向の関係があります。

例:

次の2つのテーブルがあります。


ユーザー

id:int
名前:nvarchar(50)

プロジェクト

id:int
LeadUserId:int FOREIGN KEY to Users.id
名前:nvarchar(50)



エンティティフレームワークはこれを次のような2つのクラスに変換します


ユーザー


id:int
名前:文字列
プロジェクト:リスト

事業


id:int
名前:文字列
ユーザー:ユーザー



たとえば、プロジェクトオブジェクトの「ユーザー」フィールドを別のユーザーに設定すると、プロジェクトは元のユーザーのプロジェクトリストから自動的に削除され、新しいユーザーのプロジェクトリストに追加されます。

データベースコンテキストオブジェクトで.SaveChanges()メソッドを呼び出すことにより、データベースへの変更を永続化できます。

独自の双方向関連付けを作成する

双方向関係の主な問題は、一貫性を維持する必要があることです。単純な1対1の関係ではそれほど悪くはありませんが、1対多の関係(ここでは、1人のユーザーが多くのプロジェクトに対応)の場合は少し難しくなります。

以下に、かなり優れたObservableCollectionクラスを使用する実装を示します。

Projectクラス

public class Project {
    public string Name { get; set; }

    private User _leadUser;
    public User LeadUser {
        get { return _leadUser; }
        set {
            if (_leadUser != value) {
                if (_leadUser != null) {
                    _leadUser.Projects.Remove(this);
                    if (!value.Projects.Contains(this)) {
                        value.Projects.Add(this);
                    }
                }
                _leadUser = value;
            }
        }
    }
}


Userクラス

public class User {

    public string Name { get; set; }

    private ObservableCollection<Project> _projects = new ObservableCollection<Project>();
    public ObservableCollection<Project> Projects { get { return _projects; } }

    public User() {
        Projects.CollectionChanged += OnProjectCollectionChanged;
    }

    protected void OnProjectCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
        var projects = sender as IEnumerable<Project>;
        switch (e.Action) {
            case NotifyCollectionChangedAction.Add:
                foreach (var project in projects) {
                    if (project.LeadUser != this) {
                        project.LeadUser = this;
                    }
                }
                break;
            case NotifyCollectionChangedAction.Move:
                break;
            case NotifyCollectionChangedAction.Remove:
                foreach (var project in projects) {
                    if (project.LeadUser == this) {
                        project.LeadUser = null;
                    }
                }
                break;
            case NotifyCollectionChangedAction.Replace:
                break;
            case NotifyCollectionChangedAction.Reset:
                break;
            default:
                break;
        }
    }
}


この投稿がお役に立てば幸いです。
関連記事

c# - 1人のユーザーのデータベースでトランザクションが必要ですか? [閉まっている]

c# - IDでXmlノードを取得する最も速い方法は何ですか

c# - MSB0001:内部MSBuildエラー:refCountは1未満であってはなりません

c# - C#を介してOutlookでメール送信ダイアログを開く

c# - UITableViewでランダムに「NIBをバンドルでロードできませんでした」

c# - WPFウィンドウコンストラクターを使用してカルチャを変更できますか?

c# - C#ComboBox SelectedValueはフォーカスが失われるとリセットされます

c# - DebuggerDisplay属性を使用してビットマスクを表す方法

c# - C#およびMagentostoreを使用した製品のダウンロード

c# - MVC Mini Profiler-LINQオーバーヘッド