2

既存の製品のポイント リリースである今後のプロジェクトで Microsoft の Entity Framework を使用することを検討しています。現在の製品は 2 つの DBMS (Oracle と SQL Server) をサポートしており、それぞれのスキーマは個別の .sql スクリプト ファイルに保持されています。

エンティティ フレームワーク (4.1) は、コード生成、リフレクションなどを介してさまざまなシナリオを自動的に実装できるため、魅力的に見えます。しかし、私が知る限り、これらの利点のいくつかは相互に排他的であるように見えます。

たとえば、複数の DMBS をサポートするには、モデルまたはコードを最初に設計する必要があると推測しています。その場合、EF はモデルに従ってそれぞれのスキーマを生成します (これに関する投稿やドキュメントはほとんどまたはまったく見たことがありません)。ので、間違っているかもしれません)。これは、既存のスキーマを放棄する (モデル優先) か、マップする (コード優先) 必要があることを意味します。さらに、EF はスキーマのアップグレードを (データを消去せずに) サポートしていないように見えるため、スキーマの更新には手動のスクリプトが必要になります。

  1. モデル ファーストとコード ファーストは、EF で複数の DBMS をサポートする唯一の実行可能な手段ですか? 任意の 2 つのスキーマが同じであることを保証することは技術的に不可能であることを認識しているため、これは正しいと考えています。
  2. コード ファーストと複数の DBMS システムへのマッピングの潜在的な落とし穴はありますか? たとえば、Oracle には自動インクリメント列がありません。シーケンスを使用する必要があります。これは DbContext でどのようにマップされますか? DBMS ごとに個別のマップを作成する必要がありますか?
  3. EF は、既存の DBMS スキーマを EF モデルを代表するものにアップグレードするメカニズムをサポートしていますか (スキーマの再作成 =/= アップグレード)、またはこれを手動で行うことに制限されていますか?
  4. 最初にデータベースを使用して複数の DBMS をサポートする方法を 1 つ思いつきましたが、これはメンテナンスの悪夢です。アイデアは、生成された 2 つのデータ モデルに抽象化の別のレイヤーを追加し、EF で生成されたモデルごとにコンバーター クラスを作成することでした。これは、各 DBMS が潜在的に独自のモデルを持つことができるようにするための最良の方法のように思えますが、私のコードはマッピングを処理します。しかし、これを行うことで、EF から実際に得られるものは何でしょうか? おそらくクエリ生成ですが、それだけの価値はありますか?
4

2 に答える 2

2

実際には、モデルファーストとデータベースファーストの両方に同じ制約があります。これらのアプローチは両方とも、単一のデータベースプロバイダーに直接関連するSSDL(ストアの説明=データベースレイヤー)部分を含むEDMXファイルを使用しているため、2つの異なるデータベースプロバイダーが必要な場合は、2つの異なるSSDL部分が必要です。同期します。単一のCSDL(概念レイヤーの説明=モデルクラス)と単一または2つのMSL(SSDLとCSDL間のマッピングの説明-単一のファイルは、テーブルと列が両方のSSDLでまったく同じ名前を持つ場合にのみ可能です)を使用できます)。私が知っているように、EDMXファイルは単一のSSDL、CSDL、およびMSLパーツのみで構成できるため、設計者はこのシナリオをサポートしておらず、2番目のSSDLを手動で変更するか、2つのEDMXを使用する必要があります。

コードファーストのアプローチはこれをはるかに簡単にすることができますが、問題は、コードファーストとデータベース生成を使用するときにOracleプロバイダーがどれほど優れているかということです。プロバイダーは、自動インクリメント列の場合のシーケンスなどの必要な機能を正しく解釈する責任があります。

EF自体は現在、既存のDBのアップグレードをサポートしていません。EDMXを使用する場合、データベース生成のプロセスはT4テンプレートまたはワークフローのいずれかによって制御されるため、カスタマイズでき、Entity Designer Database GenerationPowerPackと呼ばれる別個の機能がすでに存在します。これにより、モデルファーストアプローチでデータベースを段階的に構築できます。問題は、この機能がVSデータベースツールを使用していることです。これらのツールはSQLサーバーでのみ機能すると思います。私はこれらの自動化されたツールが好きではないので、データベースのアップグレードは、現在のデータベースバージョンと最後にデプロイされたデータベースバージョンの違いのスクリプトを取得するために、いくつかのツールを使用して手動で制御する必要があると思います。新しいバージョンを実稼働環境にデプロイする場合にのみ、diffスクリプトが必要です。テストおよび開発環境では、いつでもデータベース全体を再作成できます。

2つのEDMXモデルを使用する場合、抽象化は必要ありません。モデルは同じ概念レイヤーを生成する必要があります。このような場合、両方のモデルで機能するように、規則(エンティティと同じクラス名、同じタイプとアクセス可能性を持つ同じプロパティ)によってマップされるPOCOクラスの単一のセットのみが必要です。

編集:

@Tridusの回答に基づいて、最初にデータベースを作成し、EF4.1のfluentAPIを使用してデータベースをマッピングできることを追加しました。データベースはまったく同じスキーマ(テーブル名、列名など)を持っている必要があり、特定の機能を使用することはできません(Oracleが列の自動インクリメントを処理する方法であるため、シーケンスが問題にならないことを願っています)。

于 2011-04-03T09:47:20.223 に答える
1

これは実際にはデータベース ファーストの設計でかなり実行可能ですが、データベースの処理方法が異なるため、簡単に回避できないいくつかの注意事項があります。

  • シーケンスは 1 つです (EF によって完全に無視されるという点で)。挿入時にテーブルにデータを入力するトリガーをテーブルに配置することで、Oracleでそれを偽造できますが、後でモデルを更新する必要がある場合、EFは列がID列であることを「忘れ」、それを試みます。もう一度 0 を入れます。また、トリガーを使用する場合、Oracle で新しい ID を取得しようとするのは信頼できないこともわかりました。挿入を実行する前に、シーケンスから選択してオブジェクトに ID を設定するだけで済みました。これは、Oracle で通常行われている方法だからです。それを処理するストアド プロシージャを使用することもできます。

  • 数値は同じ方法で処理されません。SQL Server は、Int32、Int64 などにマップされる数値形式を使用します。Oracle の数値形式はまったく異なり、SQL Server の完全な範囲の Int32 は、Oracle では Number(10,0) です...これは実際には EF では Int64 であるため、 Int32 より大きい。また、Oracle の EF プロバイダーは、必要がない場合でも Decimal を頻繁に使用することを好みますが、これはおそらくベータ版の問題です。

  • Oracle のストアド プロシージャは、EF で機能するために、いくつかの値を app.config/web.config に入れる必要があります。それが単に SQL Server を混乱させるだけなのか、それとも問題を引き起こすのかはわかりません。

最後に、EF Code First はかなり未熟であり、ドキュメントによると、このバージョンではデータベース構造の変更をサポートしていません。オラクルのプロバイダーもそれをサポートしているかどうかはわかりません(試していない可能性があります)。

これらのほとんどは回避できるものですが、コードの残りの部分との違いを隠すためにいくつかの作業を行う必要があり、おそらくそれを行うにはラッパー層が必要になります.

編集 - #4 に関して - EF 4.1 は部分的な POCO クラスを生成できます。生成された各モデルの周りにラッパーを記述して違いを隠す代わりに、モデルの更新時に再生成されない別の部分クラス コード ファイルを作成し、違いを隠すプロパティ/メソッドを追加できます。アプリのコードは、代わりにそれらを使用することを認識している必要があり、それらは問題を処理します (私が言及した数の問題のように、Oracle に必要なキャストを実行できる別のプロパティで完全に隠すことができます)。

于 2011-04-03T10:44:22.260 に答える