これは主にアーキテクチャの問題であり、おそらく個人的な好みに少し依存します。私は長所と短所を調べようとします(実際には短所だけで、これはかなり独断的です):
データベース レベルでは、MongoDB には参照整合性を強制するツールが用意されていないため、自分で行う必要があります。次のようなデータベース オブジェクトを使用することをお勧めします。
public class DBObject
{
public ObjectId Id {get;set;}
}
public class Department : DBObject
{
// ...
}
public class EmployeeDB : DBObject
{
public ObjectId DepartmentId {get;set;}
}
何があっても、データベース レベルでこのような単純な DTO を使用することをお勧めします。追加の砂糖が必要な場合は、少しコピーすることを意味しても別のレイヤーに入れます. DB オブジェクトのロジックには、ドライバーがオブジェクトをハイドレートする方法を十分に理解している必要があり、実装の詳細に依存する必要がある場合があります。
さて、より「インテリジェントな」オブジェクトを使用するかどうかは好みの問題です。実際、多くの人は、強く型付けされた auto-activating アクセサーを使用することを好みます。
public class Employee
{
public Department
{ get { return /* the department object, magically, from the DB */ } }
}
このパターンには多くの課題があります。
Employee
データベースからオブジェクトをハイドレートできるようにするには、クラス (モデル クラス) が必要です。DBを注入する必要があるか、データベースアクセス用の静的オブジェクトが必要なため、これも注意が必要です。
- へのアクセスは
Department
非常に安価に見えますが、実際にはデータベース操作がトリガーされ、遅くなる可能性があり、失敗する可能性があります。これは発信者から完全に隠されています。
- 1 対 n の関係では、事態はさらに複雑になります。たとえば、 ?
Department
のリストも公開します。Employees
もしそうなら、それは本当にリストですかMongoCursor
?
- さらに悪いことに、どの種類のキャッシングを使用する必要があるかは通常明確ではありません。あなたが得るとしましょう
myDepartment.Employee[0].Department.Name
。明らかに、このコードはスマートではありませんが、いくつかの特殊なメソッドを含むコール スタックがあると想像してください。もっと隠されていても、彼らはそのようにコードを呼び出すかもしれません。現在、素朴な実装は、実際には、ref'dDepartment
を再度逆シリアル化します。それは醜いです。一方、実際にオブジェクトを再取得する必要がある場合があるため、積極的にキャッシュすることは危険です。
- 最悪の事態:アップデート。これまでのところ、課題は主に読み取り専用でした。ここで、 and を呼び出す
employeeJohn.Department.Name = 'PixelPushers'
としましょうemployeeJohn.Save()
。それは部門を更新しますか?もしそうなら、john への変更は最初にシリアル化されますか、それとも従属オブジェクトへの変更の後にシリアル化されますか? バージョン管理とロックはどうですか?
- 多くのセマンティクスは実装が
employeJohn.Department.Employees.Clear()
難しく、扱いにくい場合があります。
多くの ORM は一連の複雑なパターンを使用してこれらの操作を許可しているため、これらの問題を回避することは不可能ではありません。しかし、ORM は通常、10 万行から 100 万行をはるかに超えるコード行 (!) の範囲にあり、そのような時間があるとは思えません。RDBMS では、関連するオブジェクトをアクティブ化し、sth を使用する必要があります。ORM のように、明細項目のリストなどを請求書に埋め込むことはできないため、1:n または m:n の関係はすべて結合を使用して表す必要があります。これは、オブジェクト関係の不一致と呼ばれます。
私が理解しているドキュメント データベースの考え方は、RDBMS のように不自然にモデルを分割する必要がないということです。それでも、「オブジェクトの境界」があります。データ モデルを接続されたノードのネットワークと考える場合、課題は、現在データのどの部分で作業しているかを知ることです。
個人的には、この上に抽象化レイヤーを配置しないことを好みます。その抽象化は漏れやすく、実際に何が起こっているかを呼び出し元から隠し、すべての問題を同じハンマーで解決しようとするからです。
NoSQL の考え方の 1 つは、JOIN ハンマーを目に見えるテーブルに単純に適用することはできないため、クエリ パターンをデータ モデルに注意深く一致させる必要があるということです。
したがって、私の意見は次のとおりです。薄いレイヤーに固執し、データベース操作のほとんどをサービスレイヤーで実行します。ロック、mvcc、カスケード更新などを追加する必要があるとすぐにバラバラになる複雑なドメイン モデルを設計する代わりに、DTO を移動します。