2011-08-11 4 views
4

私はDDD(ドメイン駆動型設計)とリポジトリパターン(C#で)を学んでいます。リポジトリパターンを使用してエンティティを永続化し、どのデータベースが実際に使用されているか(Oracle、MySQL、MongoDB、RavenDBなど)を気にする必要はありません。私は、しかし、どのようにデータベース固有のIDを処理するか分からない:ほとんどの(すべて?)データベースが使用しています。たとえば、RavenDBでは、格納する必要がある各エンティティにstring型のidプロパティが必要です。その他にはint型のidプロパティが必要な場合があります。これは異なるデータベースで別々に処理されるため、データベースIDをエンティティクラスの一部にすることはできません。しかし、少なくとも実際の実体を保管するときは、ある時点で存在しなければならないでしょう。私の質問は、これに関するベストプラクティスは何ですか?データベース固有のID:sをリポジトリパターンで抽象化していますか?

私が現在取り組んでいる考えは、サポートしたいデータベースごとに、ビジネスオブジェクトタイプごとにデータベース固有の「値オブジェクト」を実装することです。これらの値オブジェクトはデータベース固有のidプロパティを持ち、読み取りと書き込みのときに2つの値をマップします。これはいい考えのようですか?

+1

本当に必要ですか?あなたが遭遇するメンテナンス地獄のために、私にとっては良い考えではないようです。 – xelibrion

+0

私はxelibrionに同意します。 – NotMe

+0

私は同じ問題に直面しています。残念ながら、ここに挙げた解決策のどれもが私を「完璧な解決策」としています(もしあれば...)。また、データ抽象化レイヤー内の特定の実装タイプにキャストすることも考えました。つまり、 'DTO'と' DAO'はすべてのDB型に共通のインターフェースですが、特定の 'DAO'実装はそのメソッド内の' DTO'を同じ特定の実装型にキャストします一度に1つのDBタイプしか使用されないと仮定します)。これにより、特定のIDを使用することができます。それは汚れているようですが、私が今までに思いついたのは最高です。 – eitanfar

答えて

0

エンティティにIDを含めることはできますが、エンティティのパブリックインターフェイスの一部として公開することはできません。これはNHibernateで可能です。テーブルカラムをプライベートフィールドにマッピングできるからです。

ですから、潜在的にあなたの永続ロジックがビジネスロジックに「出血」が、それはおそらく、エンティティとその間のマッピングを維持するより簡単に、より堅牢で要件を与えられたので、これは理想的ではありません

class Customer { 
     private readonly Int32? _relationalId; 
     private readonly String? _documentId; 
     ... 

のようなものを持つことができますidの外側のどこかのid。リレーショナル・データベースのみをサポートしたい場合には、より現実的な「データベースにとらわれない」アプローチを評価することを強くお勧めします。この場合、リポジトリ実装のために少なくともNHibernateのようなORMを再利用することができます。そして、ほとんどのリレーショナルデータベースは同じid型をサポートしています。あなたのシナリオでは、ORMが必要なだけでなく、 "Object-Document-Mapper"のようなものも必要です。トンとトンのインフラストラクチャコードを書く必要があることがわかります。 の要件を再評価し、リレーショナルデータベースとドキュメントデータベースを選択することを強くお勧めします。これを読んでください:Pros/cons of document-based databases vs. relational databases

3

これは、抽象の漏れの古典的なケースです。リポジトリインタフェースの下で、各データベースに付属している良いものをすべて失うことがない限り、データベースの種類を抽象化することはできません。 IDタイプ(文字列、Guidなど)の要件は、泥水の下で大部分の大量の巨大な氷山の頂点に過ぎません。

トランザクションの処理、並行性などについて考えてみましょう。私は、永続性の無知についてのあなたの点を理解しています。ドメインモデルの特定のデータベーステクノロジに依存しないようにしてください。しかし、永続化技術への依存もなくすことはできません。

ドメインモデルをどのRDBMSでもうまく動作させることは比較的簡単です。それらのほとんどは標準化されたデータ型を持っています。 NHibernateのようなORMを使用すると、多くの助けになります。 NoSQLデータベース間でも同じことを達成するのはずっと難しい(実際には非常に良い)。

私は、対処しなければならない可能性のある永続テクノロジのセットについていくつかの調査を行い、次に永続サブシステムの適切な抽象レベルを選択することをお勧めします。

これがうまくいかない場合は、Event Sourcingを考えてください。イベントストアは、最も要求の厳しい永続化手法の1つです。 Jonathan Oliverのなどのライブラリを使用すると、ファイルシステムを含むあらゆるストレージテクノロジを事実上使用できます。

+2

いいえ、これは逆です - 漏れた抽象を避ける古典的なケースです。ストアのIDタイプをオブジェクトのグローバルな「フレンドリな」参照として使用すると、漏れが生じます。ストアは、IDが正常であり、通常は必要であることを維持します。通常は2つのものがうまく一致します。このチャプチャは2つを分離しようとしているので、この問題を解決する必要があります。 – Chalky

+0

@Chalky DBなどの主要なAPIプロバイダについては、あまりにも抽象的なものはありません。あなたがコード内のどこでも特定のIDタイプを使用するほどDB型に頼っているなら、あなたはDBを変更することはできません...まあ、実質的に永遠に!企業は、DBがデータでいっぱいになると、使用しているDBを別のものに置き換えることに消極的である。なぜなら、ほとんどの場合、大部分は時間がかかるからである。これはまた、完全に新しい実装を提供することを意味する。特定のIDタイプを想定しています。 – eitanfar

1

私は、エンティティにint Idフィールドを作成し、そのIDを文字列にする必要があるリポジトリ内の文字列に変換します。私はあなたの永続性を抽象化する努力が非常に価値があり、実際にメンテナンスを容易にすると思います。

1
  1. あなたはことをやっています!データベースの主キータイプの制約からあなた自身を抽象化してください!

  2. タイプを変換しようとしないで、別のフィールドを使用してください。

具体的には、データアクセスロジック以外は、データベースの主キーを使用しないでください。オブジェクトにフレンドリーなIDが必要な場合は、好きなタイプのフィールドを追加してデータベースに保存するようにしてください。データアクセス層でのみ、&がオブジェクトのフレンドリーIDに基づいてDBレコードを更新する必要があります。簡単です。

次に、オブジェクトを永続化できるデータベースの制約が「xxxx型の主キーを持つ必要があります」から「xxxx型を格納できる必要があります」に変更されました。私は、あなたが世界のどのデータベースを使用してもあなたを見つけることができると思います。ハッピーコーディング! DDDが最高!

+0

私も同様の問題を抱えています。あなたが何を示唆しているのが私の心に来た最初のことです。しかし、私がバグを報告した唯一の事は、DB内のほとんどすべてのオブジェクトに2つの異なるID型フィールドが作成されるということです。 – eitanfar

関連する問題