4

次のような一般的なリポジトリ インターフェイスがあるとします。

public interface IRepository<T>
{
    Add(T item);
    Delete(int itemId);
    Update(T item);
}

通常、IRepository.Add() を介して追加されたアイテムの新しい ID は、何らかのバックエンド データベースによって決定されますが、トランザクション全体または作業単位が送信された後にのみ決定されます。したがって、追加されたアイテムの新しい ID を IRepository.Add() が返すのは間違っていると確信しています。リポジトリは、ID がどのように作成されるかについて、実際には何も認識すべきではありません。これは正しいです?

この場合、リポジトリに追加されたアイテムの新しい ID を他にどのように判断できますか、またはこれを行う必要がありますか? NHibernate のような ORM は、メモリ内のオブジェクトを正しい ID を持つ新しいオブジェクトに自動的に置き換えることができることを知っていますが、特定の ORM 実装を念頭に置いてリポジトリを設計しようとしています。

たとえば、顧客が注文できる Web サイトがあるとします。新しい顧客がチェックアウトを選択すると、詳細を入力するフォームに送信されます。この情報は、CustomerRepository に格納される Customer オブジェクトを作成するために使用されます。注文情報を作成する必要がありますが、注文は ID で顧客を参照する必要がありますか?

Customer newCustomer = new Customer(first, last, address, phone dateOfBirth);
customerRepository.Add(newCustomer);

//How would I determine customerId??
Order newOrder = new Order(customerId, shippingAddress, billingAddress);
newOrder.AddOrderItem("widget");
newOrder.AddOrderItem("doohicky");
newOrder.AddOrderItem("stuff");
4

6 に答える 6

3

あなたが与える例では、IDを渡す代わりに、1つのステップでandを作成し、ドメインオブジェクトをドメインオブジェクトに渡しますCustomerOrder

Customer newCustomer = new Customer(first, last, address, phone dateOfBirth);

// Pass the customer rather than the CustomerId:
Order newOrder = new Order(newCustomer , shippingAddress, billingAddress);
newOrder.AddOrderItem("widget");
newOrder.AddOrderItem("doohicky");
newOrder.AddOrderItem("stuff");

customerRepository.Add(newCustomer);
orderRepository.Add(newOrder);

// SaveChanges()

...変更が保存されると、オブジェクトが に割り当てられているため、フレームワークはCustomerとの両方の ID を自動的に入力し、 、、 (など)Orderを埋めます。Customer.IdOrder.customerIdCustomerOrder

于 2011-06-08T10:46:40.367 に答える
2

クライアントで id を生成し (a la CombGuid.NewGuid())、それをコンストラクターに渡します。データベース ID を使用している場合のアプローチには重大な欠点があります

于 2011-06-08T09:38:15.083 に答える
1

エリック、

あなたが言及したシナリオでは、CommitChanges() が進行しているとは思いません。すべてを transactionscope にラップしてから、オーダーラインを追加する前に customerRepository.CommitChanges() を押します。これで、新しく作成された顧客オブジェクトから ID を取得し、次のように使用できるようになります。

Order newOrder = new Order(newCustomer.Id, shippingAddress, billingAddress);

次に、注文が失敗した場合は、すべてをロールバックして、scope.Complete() をヒットしないことでアトミックに保つことができます。

お役に立てれば..

于 2011-06-08T09:30:38.293 に答える
0

DDDによると、インターフェースはリポジトリよりもDAOです。

http://codebetter.com/iancooper/2011/04/12/repository-saveupdate-is-a-smell/

Steve Wilkes が述べたように、Customer Id ではなく Customer の参照を順番に保持する必要があるため、Unit of Work が処理されると、Persistence Storage (SQL DB、Web Service など) 内のエンティティへの正しいリンクが作成されます。

DAO の詳細については、http: //java.sun.com/blueprints/corej2eeppatterns/Patterns/DataAccessObject.htmlを参照してください。

于 2011-06-09T02:10:41.607 に答える
0

NHibernate を使用するかどうかに関係なく、NHibernate のアプローチは正しいと思います。ドメイン オブジェクトの目標は、一度にそのオブジェクトのインスタンスを 1 つだけメモリに保持することです。つまり、同じデータベース レコードを表す 2 つのオブジェクトを保持しないようにする必要があります。したがって、データベースが新しい ID でレコードを更新した場合、メモリ内のドメイン オブジェクトもその ID で更新する必要があります。これは、その ID がそのレコードの「1 つの」真の表現であるためです。

を呼び出した後Add、オブジェクトの ID が設定され、そのオブジェクトにさらに変更を加えてUpdate、実装についてあまり知らなくても呼び出すことができます。

于 2011-06-08T09:48:49.017 に答える
0

ドメイン エンティティはデータベース ID に関係なく独自の ID 戦略を持つ必要があるため、できればドメイン レイヤーで ID を生成するか、データベースで ID を生成する必要がある場合は、データベースの自動生成 ID の横にドメイン レイヤーで生成された別のドメイン ID を追加します。

リポジトリ パターンを適用するドメイン駆動設計では、ドメインをデータベースと結び付けるべきではないため、ID の作成をデータベースに依存することはお勧めできません。

もう 1 つのポイントは、顧客 ID を配置するだけでなく、顧客を関連付けることができるようにすることです。これにより、ドメイン層がリッチで堅牢になります。

于 2012-01-05T23:37:00.130 に答える