2

Entity オブジェクトにリポジトリ インターフェイスを注入することは Persistance Igorance に違反しているのでしょうか。このように。インターフェースを使用しないことで明らかに問題が見えますが、インターフェースを使用すると本当に問題があるのでしょうか? 以下のコードは良いパターンですか、それとも悪いパターンですか?またその理由は?

public class Contact
{
    private readonly IAddressRepository _addressRepository;

    public Contact(IAddressRepository addressRepository)
    {
        _addressRepository = addressRepository;
    }

    private IEnumerable<Address> _addressBook;
    public IEnumerable<Address> AddressBook
    {
        get
        {
            if(_addressBook == null)
            {
               _addressBook = _addressRepository.GetAddresses(this.Id);
            }
            return _addressBook;
        }
    }
}
4

4 に答える 4

1

これは必ずしも良い考えではありませんが、一部の限られたシナリオでは問題ない場合があります。Addressが集約ルートであるとは信じがたいので、私はあなたのモデルに少し混乱しています。したがって、本格的なアドレスリポジトリを持つことは普通ではありません。あなたの例に基づくと、おそらく実際にはリポジトリではなくテーブルデータゲートウェイまたはdaoを使用しています。

私はこの問題を解決するためにデータマッパーを使用することを好みます(ORMまたは同様の解決策)。基本的に、私はORMを利用して、アドレスブックを集約ルート「Contact」の遅延ロードされたプロパティとして扱います。これには、エンティティがセッションにバインドされている限り、変更を保存できるという利点があります。

ORMを使用していなかった場合でも、具体的なContactリポジトリの実装でAddressBookバッキングストア(リストなど)のプロパティを設定することをお勧めします。その列挙を他のデータストアを認識しているプロキシオブジェクトにリポジトリセットして、オンデマンドでロードする場合があります。

于 2010-07-15T18:00:44.980 に答える
0

質問してから2年が経ちましたが、少し誤解されていたので、自分で答えようと思います。

言い換えられた質問:「ビジネスエンティティクラスは完全に永続性を無視する必要がありますか?」

エンティティクラスは完全に永続性を無視する必要があると思います。コードベースの多くの場所でエンティティクラスをインスタンス化するため、常にリポジトリクラスをエンティティコンストラクタに挿入する必要があり、非常にきれいに見えないため、すぐに面倒になります。複数のリポジトリを注入する必要がある場合、これはさらに明白になります。したがって、私は常に別のハンドラー/サービスクラスを使用して、エンティティの永続化ジョブを実行します。これらのクラスは、インスタンス化される頻度がはるかに少なく、通常、これが発生する場所とタイミングをより細かく制御できます。エンティティクラスは可能な限り軽量に保たれます。

現在、私は常に1つのリポジトリprアグリゲートルートを持っています。エンティティがリポジトリからフェッチされるときに追加のビジネスロジックが必要な場合は、通常、アグリゲートルート用に1つのServiceClassを作成します。

悪い例だったので、質問のコードの微調整された例を取ることによって、私は今このようにします:

それ以外の:

public class Contact
{
    private readonly IContactRepository _contactRepository;

    public Contact(IContactRepository contactRepository)
    {
        _contactRepository = contactRepository;
    }

    public void Save()
    {
        _contactRepository.Save(this);
    }
}

私はこのようにします:

public class Contact
{

}

public class ContactService
{
    private readonly IContactRepository _contactRepository;

    public ContactService(IContactRepository contactRepository)
    {
        _contactRepository = contactRepository;
    }

    public void Save(Contact contact)
    {
        _contactRepository.Save(contact);
    }
}
于 2013-02-22T15:39:51.020 に答える
0

通常、DDD に従う場合は、常に集計全体を操作します。リポジトリは常に、完全にロードされた集約ルートを返します。

あなたの例のようにコードを書くことは(少なくともDDDでは)あまり意味がありません。Contact 集約には、常にすべてのアドレスが含まれます (その動作にアドレスが必要な場合は、正直言って疑わしいです)。

したがって、通常、ContactRepository は、Address がエンティティ、またはおそらくこの集約内の値オブジェクトである Contact 集約全体を構築することを想定しています。

Address は Contact 集約に属する (したがって、それによって管理される) エンティティ/値オブジェクトであるため、この集約外の集約に属するエンティティを管理することは想定されていないため、独自のリポジトリはありません。

Resume: 常に Contact 全体をロードし、その動作メソッドを呼び出して、その状態で何かを行います。

于 2013-02-22T13:47:03.567 に答える
0

load 関数を外部から注入できます。.NET 4.0の新しいLazy<T>型は、そのために便利です。

    public Contact(Lazy<IEnumerable<Address>> addressBook)
    {
        _addressBook = addressBook;
    }

    private Lazy<IEnumerable<Address>> _addressBook;
    public IEnumerable<Address> AddressBook
    {
        get { return this._addressBook.Value; }
    }

IEnumerable<T>また、クエリ プロバイダーからそれらを取得する場合、s は本質的に怠惰である可能性があることにも注意してください。ただし、他のタイプの場合は、Lazy<T>.

于 2010-07-29T15:05:46.587 に答える