1

MVC アプリケーションを 3 タイヤ アプリケーションの UI レイヤーとして使用し、EF CodeFirst 5 を DAL として使用して、ASP.NET MVC C# アプリケーションを開発しています。

DAL -> DTL
DTL <- BLL -> DAL
DTL <- UI -> BLL

矢印は用途を意味します。(だからDALはDTLなどを使う...)

私は、EF Code First に沿ったデータ関連の検証を行うデータ転送オブジェクトとして POCO を使用しました。私の POCO には関係があり、関係にある POCO には関係があります。かなり標準的な...

BL のすべてのクラスは、単一の責任規則に従って、単一の POCO タイプを処理します。私を悩ませているのは、POCO が他の BL の関心事である関係を持っている場合 (単一の責任を維持するために)、POCO にビジネス ルールと検証をどのように適用するかということです。

簡単な例を挙げてみます:(これを擬似コードとして読んでください)

public class Customer{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Enumerable<Person> Users { get; set; }
}

public class Person{
    public int Id { get; set; }
    public string Name { get; set; }
    public Customer BelongsTo { get; set; }
    public virtual Enumerable<Property> Properties { get; set; }
}

public class Property{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Value { get; set; }
}
public class CustomerBL{

    private DALContext = new DALContext();        

    public void Add(Customer customer){
        DALContext.Customers.Add(customer);
        DALContext.SaveChanges();
    }
}

public class PersonBL{

    private DALContext = new DALContext();        

    public void Add(Person person){
        if(person.Properties.Count() < 3)
             throw new ApplicationException("Each person must have at least three properties");

        DALContext.People.Add(person);
        DALContext.SaveChanges();
    }
}

したがって、私の質問は、新しい顧客を追加するときに、すべてのユーザー (顧客オブジェクトに設定されている場合) が、単一の責任ルールを破ることなく (または少なくともいい意味で壊してください)?

Person は、他の関係を持つ他の関係を持つことができ、すべてがビジネス ルールを持つ特定の BL を持つことに注意してください。「具体的な」例を提供しましたが、より一般的な解決策を探しています。ありがとうございました!

4

3 に答える 3

2

集約ルートの設計を確認する必要がある場合があります。

AR は常に一貫した状態でなければならないことに注意してください。検証すべきではないものを検証する必要があることがわかった場合は、集約ルートが拡張しすぎています。これは、オブジェクト モデルをナビゲーションの観点から考えた場合に発生する可能性があります。AI は B から C に移動したいと考えています。これは、非常に簡単につまずく場所です。クエリにドメイン モデルを使用しない場合、ナビゲーションは必要ありません。遅延読み込みは、ドメイン モデルをクエリ/ナビゲーションに使用するもう 1 つの症状です。

あなたの例では、と呼ばれるエンティティCustomerのリストがあります。Aは別の AR のようです。AR に他の AR のインスタンスを含めるべきではありません。その絆を断ち切ってください。PersonUsersPerson

したがって、 aには(またはドメインで意味Customerのあるもの) のリストがある場合があります。Usersユーザーは次の構造を持つ場合があります。

public class User{
    public int PersonId { get; set; }
}

それと同じくらい簡単です。他の場所でメンテナンスされているので、もう心配する必要はありませんPerson。したがって、問題の AR では、他の集約ルートを値オブジェクトとして表すようにしてください。

于 2013-03-05T04:33:17.527 に答える
1

バリデーションを行う別のバリデータークラスを作成するのはどうですか? 次に、特定のエンティティの検証を行う必要があるときはいつでも、その作業をバリデーターに渡すことができます。バリデーターは壊れたルールを返します。これにより、Person リポジトリだけでなく、パーソンを作業単位の一部として追加する可能性のある他の領域でもバリデーターを再利用できます。この手法は、私が見たいくつかのビジネス オブジェクト フレームワークで使用されており、検証を他の主要なビジネス ロジックから独立させ、テストを容易にします。 これは、この件に関する良い投稿です。

于 2013-03-04T14:55:17.017 に答える
1

関係の正しい方向を確立することは非常に重要です。

通常、適切な方法は、エンティティ クラス内のコレクション プロパティを削除することです。あなたの特定のケースでは、これらはCustomer.UsersPerson.Propertiesです。に注目しましょうCustomer.Users。プロパティを作成するUsersと、ユーザーのリストがCustomerエンティティに不可欠であることを示します。しかし、矛盾が見られます

すべてのユーザー (顧客オブジェクトに設定されている場合) が検証されていることを確認します

ユーザーのリストがなくても顧客が存在できることがわかります。ここで問題は、Userがなくても存在できるということCustomerです。おそらくそうではありません (そうであれば、別のタイプのユーザーである可能性があります)。したがって、関係の方向を反転すると、エンティティのCustomerプロパティが作成され、エンティティのコレクション プロパティUserが削除されます。UsersCustomer

コレクション プロパティは POCO の特に仮想メンバーには適していないと主張する人もいるかもしれないので、これにより POCO の設計が改善されます。

では、設計を改善することはできますが、関係自体をどのように検証すればよいのでしょうか? 答えは、このタスクを実行するには別のエンティティが必要だということです。たとえば、2 つのオーバーロードをCustomerRegistrationJournal持つメソッドを持つことができます。1つは関連するユーザーがいない場合のエンティティを取得し、もう 1 つは関連するアカウントのリストを取得します。このメソッドは、各エンティティの検証を呼び出し、DAL を呼び出します。このようにして、2 種類のエンティティを作成するトランザクションを制御します。RegisterCustomerCustomerCustomerUser

この場合の DAL は、 をUser参照する列に外部キー制約を適用するようにモデル化する必要がありCustomerます。このようにして、それは弱い関係を提供します。つまり、ロードはロードUserされずCustomer、更新や削除のカスケードは行われません。Userエンティティには、IdテーブルCustomerと同じように がありUserます。これIdは にとって不可欠ですがUserCustomer のコンポーネントではありませんUser。もちろん、全体Customerをプロパティとして持つようにモデル化できますが、それは不要なオーバーヘッドになります (NHibernate の遅延読み込みを使用しても)。

異なる設計戦略をモデリングに適用する必要がありますPerson.Properties。何らかの理由で、 Person の一部の属性は、Property 値オブジェクトのリストで表す必要があります。値オブジェクトはエンティティなしでは存在しません。値オブジェクトは他のエンティティのコンポーネントであり、エンティティと一緒に読み込んで更新する必要があります。これは、強力な 1 対多の関係です。これは、ORM の完全な可能性が必要とされる場所です。

于 2013-03-04T15:10:39.940 に答える