大規模システムのEntity Framework-モデルの分割方法


50

私は、1000以上のテーブル、さらに数百のビュー、数千のストアドプロシージャを備えたSQL Serverデータベースを使用しています。新しいプロジェクトにEntity Frameworkの使用を開始したいと考えており、そのための戦略に取り組んでいます。ハングアップしているのは、テーブルを異なるモデルに分割する最良の方法です(最初にコードを作成する場合は、EDMXまたはDbContext)。私はすぐにいくつかの戦略を考えることができます:

  • スキーマによる分割
    テーブルはおそらく12個のスキーマに分割されています。スキーマごとに1つのモデルを作成できます。ただし、dboは500を超えるテーブル/ビューで非常に大きくなるため、これは完全ではありません。もう1つの問題は、特定の作業単位が複数のモデルにまたがるトランザクションを実行しなければならないことです。これにより、EFがこれをかなり簡単にすると仮定します。
  • 意図
    で分割するスキーマを気にする代わりに、モデルを意図で分割します。そのため、取得する粒度に応じて、アプリケーション、プロジェクト、モジュール、または画面ごとに異なるモデルを用意します。これに伴う問題は、UserやAuditHistoryなど、すべての場合に必ず使用する必要がある特定のテーブルがあることです。それらをすべてのモデルに追加しますか(DRYに違反すると思います)、それともすべてのプロジェクトで使用される別のモデルにありますか?
  • まったく分割しないでください-1つの巨大なモデル
    これは開発の観点からは明らかにシンプルですが、私の研究と直感から、設計時、コンパイル時、そしておそらく実行時の両方でひどく実行できるようです。

このような大規模なデータベースに対してEFを使用するためのベストプラクティスは何ですか?具体的には、この大量のDBオブジェクトに対してモデルを設計する際にどのような戦略を使用しますか 私が上で持っているものよりもうまく機能すると思っていないオプションはありますか?

また、これはNHibernateなどの他のORMの問題ですか?もしそうなら、彼らはEFよりも優れたソリューションを考え出しましたか?


「複数のモデルにまたがるトランザクションを実行する必要があるため、複雑さが増します」Microsoft分散トランザクションコーディネーターを有効にする必要があることに注意してください。一度それを実行すると、あなたが話していることを簡単に達成できるはずです。
Tjaart

@Tjaartありがとう。以前にMS DTCを使用したことがありますが、かなり単純ですが、単純なDB txnを超える複雑さを追加するため、可能な限り避けたいと思います。
RationalGeek

2
4年後、あなたは何を決めましたか、そして今何をお勧めしますか?
ロリー

回答:


31

個人的には、かなり複雑だが小さなプロジェクト(〜300テーブル)で、すべてのエンティティに対して1つの巨大なスキーマを作成しようとしました。多くの「多対多」の関係と極端な参照整合性の強制を備えた、非常に正規化されたデータベース(5番目の形式の正規化(緩やかに言う))がありました。

また、「リクエストごとの単一インスタンス」戦略も使用しましたが、これも助けになるとは思いません。

単純で、合理的にフラットな「明示的に定義された」リストを作成するとき、パフォーマンスを検索して保存することは一般に許容できました。しかし、深い関係を掘り始めたとき、パフォーマンスは劇的に低下したように見えました。このインスタンスのストアドプロシージャと比較すると、(もちろん)比較はありませんでした。パフォーマンスを向上させるためにコードベースをあちこち調整できたはずですが、この場合は時間の制約のために分析せずにパフォーマンスを向上させる必要があり、ストアドプロシージャにフォールバックしました(まだマップされていました) EFを通じて、EFは厳密に型指定された結果を提供したため)、いくつかの領域でのフォールバックとしてのみ必要でした。コレクションを作成するためにデータベース全体を走査する必要があったとき(.include()をparしみなく使用)、パフォーマンスは著しく低下していましたが、多すぎます。

私の経験に基づいて、インテントごとに別個の.edmxを作成することをお勧めします。そのニーズの範囲に基づいて、使用するもののみを生成します。目的のタスク用に小さなスコープの.edmxファイルがあり、次に複雑な関係をトラバースしてオブジェクトを構築する必要がある大きなファイルがあります。私はその魔法の場所がどこにあるのか分かりませんが、1つあると確信しています...笑...

正直なところ、いくつかの落とし穴(複雑なトラバース)を除いて、巨大な.edmxは「作業」の観点からはうまく機能しました。ただし、明示的に無効にしない場合は、コンテキストが舞台裏で行う「修正」マジックに注意する必要があります。データベースへの変更が行われたときに.edmxの同期を維持するだけでなく、サーフェス全体を消去してエンティティを再作成するのが簡単な場合がありました。これには3分ほどかかりました。

これはすべてEntityFramework 4.1で行われました。あなたの最終選択と経験についても聞いてみたいです。

nHibernateの質問に関して、それは私の意見ではワームの質問です、フェンスの両側でbarえるでしょう...私は多くの人々が、 EF自体に特有のニュアンスの課題と理解ドラッグアンドドロップで生成し、LINQを使用してCRUDとクエリを開始できるので、粒度についてがらくたをすることができます。

これがお役に立てば幸いです。


1
参考までに、これらのマッピングを非常に簡単かつ自動化するNHibernateマッピングユーティリティがあります。
ガンダー14

@ganders-UIがあり、IDE統合はどうですか?私はあなたがそれをデータソースに向け、参照整合性とオブジェクトトラバーサルを尊重し、マッピングオブジェクトを作成すると仮定していますか?
ハンゾロ14

1
はい(GUI)。私はこれまでにこれに関してゼロの問題を抱えてきました。4つまたは5つの異なるプロジェクト/ウェブサイトで使用しました。注:config / xmlファイルではなくc#コードでマッピングを行うFluent NHibernateで使用します。リンクは次のとおり
ganders

13

簡単な説明から始めましょう。このような大規模なデータベースの経験がないので、残りの答えは実世界の例に基づいていません。

したがって、BIGデータベースがあり、それをORM / EFで使用する必要があります。私は2番目の選択肢に行きます。理由は次のとおりです。

  • マッピングは複雑さを増します。現在のアプリケーション/プロジェクト/モジュールが必要としないエンティティを複雑にする必要はありませんが、粒度を低くしすぎないでください。画面ごとに個別のマッピングを設定しても、役に立ちません。
  • 作業単位を達成したい。ほとんどの場合に必要なテーブルモジュールを指定できる必要があります(すべての場合に必要なわけではありません)。これらのテーブルを単一のマッピングセットに入れると、単一のコンテキストインスタンスによる読み取りとデータ変更を処理できるようになります。これが最終的なターゲットです。
  • モデルが何を意味するのか正確にはわかりませんが、異なるマッピングセットを使用しても、同じエンティティタイプを使用してマッピングセット間でクラスを共有できます。したがって、2つのモジュールでUserテーブルを使用する場合、同じものを表すために2つのUserクラスは必要ありません。単一のテーブルを引き続き使用でき、コードマッピング(別名コードファースト)の場合、マッピングを一度定義して複数のマッピングセットにロードすることもできるため、DRY原則に違反することはありませんが、コードファーストアプローチには制限がありますビューとストアドプロシージャ。EDMXはこれを難しくします。クラスは引き続き再利用できますが、マッピングの再利用は不可能です。
  • クロスモジュールクエリはどうですか?これらのクエリは発生する可能性がありますが、正直なところ、すべてをEFで処理する必要はありません。一般的な場合にEFを利用して通常のデータアクセスを簡素化できますが、5つの異なるモジュールに属するテーブルを結合する特別なクエリが必要な場合は、直接実行するか、ストアドプロシージャにラップすることができます。ネイティブデータアクセスの100%置換は、難しく、複雑で、逆効果です。
  • 最後の点は単純に実用的です。VSツールは、デザイナーではなく、インポートツールでさえも、このような大きなオブジェクトセットで動作する準備ができているとは思いません。VS2008では、従来のデータアクセスとSQLデータベースプロジェクトを使用して非常に大規模なデータベースで作業していました。複雑なプロジェクトでのユーザーエクスペリエンスは非常に悪かったです。使用するテーブルの数を少なくする必要があります-デザイナーの上限は100から200の間であるはずですコンテキストで公開されている-それは良いデザインのようには見えません)。

4

この種の質問を技術的な観点から決定することはできないと思います。ユースケース(ユーザーストーリーなど)に基づいてアーキテクチャを構築することをお勧めします。最初にビジネスオブジェクトを見つけます。エンティティオブジェクトは、デフォルトではビジネスオブジェクトではありません。通常、エンティティオブジェクトの前にビジネスオブジェクトがあります。その後、ユーザーの要件に基づいて、本当に必要なものを段階的に決定できます。

「優れたアーキテクトは、行われない決定の数を最大化します。」ロバート・C・マーティン

http://cleancoder.posterous.com/architecture-deference


3

私はハイブリッドアプローチを使用します。OLTPスタッフはEFによって処理され、バッチ挿入、大量更新、レポートクエリなどの負荷の高い操作はStored Procsによって処理されます。また、データレイヤーの完全な再書き込みを一度に行わない場合、移行パスが容易になります。


これは良い戦略のように思えますが、異なるEFモデルにエンティティを分割する方法の問題には実際には対応していません。1つのモデルにすべてのエンティティがありますか、それとも何らかの方法で分割して征服しますか?
RationalGeek

1
フルモデルのアプローチでOLTPのパフォーマンスが十分である場合は、そのままにしてください。必要に応じて後からいつでも分割できますが、最も迅速で最も機敏な方法は、すべてをロードすることです。それを分割することで得られるパフォーマンスの向上が必要になることはないので、時間を無駄にし、理由もなくシステムをより複雑にします。次に、拡張を決定するときに、どのモデルに新しいテーブル/エンティティを固定するかという問題があります。そして、複数のモデルにわたって更新を実行する必要がある場合にどうなりますか。本当に代替手段がない場合を除き、頭痛を避けてください。
ニック

データにアクセスするときは常にパフォーマンスを微調整できることを忘れていました。遅延/熱心な読み込みオプションと、どの子エンティティを取り込むかを見てください。大規模なオブジェクトツリーを読み込まない場合、完全なモデルが小さいモデルよりも悪い動作をする理由はわかりません。
ニック

大きなスキーマを扱う場合、大規模なオブジェクトツリーと正規化されたデータ構造が手に
渡ると言い

オブジェクトグラフを飽和させる量を制御します。
ニック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.