web-dev-qa-db-ja.com

ストアドプロシージャの代わりにORMを使用する方法を教えてください。

すべてのデータアクセスにストアドプロシージャのみを使用する会社で働いているため、新しいプロシージャを実行するたびにコミットするたびにローカルデータベースの同期を保つのは非常に面倒です。私は過去にいくつかの基本的なORMを使用しましたが、その経験ははるかに良く、すっきりしています。私は将来の開発に何らかのORMを使用することを検討していることを開発マネージャーと残りのチームに提案したいと思います(残りのチームはストアドプロシージャに精通しており、他には何も使用していません)。現在のアーキテクチャは.NET 1.1のように書かれた.NET 3.5で、「神のクラス」はActiveRecordの奇妙な実装を使用し、コードビハインドファイルでループされる型なしのDataSetを返します-クラスは次のように機能します。

class Foo { 
    public bool LoadFoo() { 
        bool blnResult = false;
        if (this.FooID == 0) { 
            throw new Exception("FooID must be set before calling this method.");
        }

        DataSet ds = // ... call to Sproc
        if (ds.Tables[0].Rows.Count > 0) { 
            foo.FooName = ds.Tables[0].Rows[0]["FooName"].ToString();
            // other properties set
            blnResult = true;
        }
        return blnResult;
    }
}

// Consumer
Foo foo = new Foo();
foo.FooID = 1234;
foo.LoadFoo();
// do stuff with foo...

デザインパターンの適用はほとんどありません。テストはまったくありません(単体テストの作成方法を誰も知らないため、テストは手動でWebサイトをロードして、ざっと見ていきます)。データベースを見ると、199個のテーブル、13個のビュー、なんと926ストアドプロシージャ、93個の関数があります。約30ほどのテーブルがバッチジョブまたは外部のものに使用され、残りはコアアプリケーションで使用されます。

このシナリオで別のアプローチを追求する価値がありますか? 「機能する」ので既存のコードをリファクタリングすることが許可されていないため、ORMを使用するように既存のクラスを変更できないため、前に進むことについて話しているだけですが、代わりに新しいモジュールを追加する頻度がわかりません現在のモジュールに追加/修正するため、ORMが適切なアプローチであるかどうかはわかりません(ストアドプロシージャとデータセットへの投資が多すぎる)。それが正しい選択である場合、それを使用するためのケースをどのように提示すればよいですか?私の頭の上で私が考えることができる唯一の利点は、よりクリーンなコードを持っていることです(ただし、現在のアーキテクチャはORMを考慮して構築されていないため、基本的には将来のモジュールにORMを厳しくリギングしますが、古いものはまだDataSetsを使用しており、どのプロシージャスクリプトが実行され、どれが実行される必要があるかなどを覚える必要はほとんどありませんが、それだけです。保守性も気になるところですが、私以外誰も気にしていないようです。

31
Wayne Molina

ストアドプロシージャは不適切です。低速であり、通常のクライアント側コードとほぼ同じくらい効率的です。

[スピードアップは通常、クライアントとストアドプロシージャのインターフェイスの設計方法と、トランザクションがSQLの集中的なバーストとして書き込まれる方法によるものです。]

ストアドプロシージャは、コードを配置する最悪の場所の1つです。ランダムであることが多い規則に従って、アプリケーションを2つの言語とプラットフォームに分割します。

[この質問のスコアは-30程度に低くなります。なぜなら、多くの人が、ストアドプロシージャには魔法の力があり、問題が発生しても使用する必要があるためです。]

すべてのストアドプロシージャコードをクライアントに移動すると、誰にとっても非常に簡単になります。

それでも、スキーマとORMモデルを時々更新する必要があります。ただし、スキーマの変更はORMの変更から分離されているため、アプリケーションとデータベーススキーマをある程度独立させることができます。

これらのストアード・プロシージャーを書き直すときに、それらすべてをテスト、修正、保守、理解、および調整することができます。アプリはほぼ同じように実行され、2つの異なるテクノロジーに侵入することがなくなるため、脆弱性が大幅に軽減されます。

ORMは魔法ではありません。ORMを機能させるには、優れたデータベース設計スキルが不可欠です。

また、多くのクライアントSQLを含むプログラムは、トランザクションの境界について十分に考えていないために遅くなる可能性があります。ストアドプロシージャが高速であると思われる理由の1つは、ストアドプロシージャがトランザクションを非常に慎重に設計する必要があるためです。

ORMは注意深いトランザクション設計を魔法のように強制しません。トランザクションの設計は、ストアドプロシージャを作成するときと同じように慎重に行う必要があります。

48
S.Lott

ストアドプロシージャは優れており、高速で非常に効率的であり、データ関連のコードを配置するのに理想的な場所です。そのすべてのコードをクライアントに移動すると、クライアント開発者として少し簡単になります(コミットするとスキーマとORMモデルを更新する必要があるため、若干変更されます)が、既存のコードはすべて失われ、これらのすべてのSQLスキルの喪失を考慮すると、アプリは遅くなり、おそらくより壊れやすくなります。

DBAが「ああ、すべてのコミット、クライアントをもう一度引き下げなければならない。代わりにすべてのコードをDBフォームに移動する必要がある」と言っているのだろうか。

あなたのケースでは、既存のカスタムORM(つまり面白いクラス)を他の誰かと置き換えることができ、コードビハインドコードの記述方法の変更を除いて何の損失もありません。ほとんどの(すべての)ORMが喜んでそれらを呼び出すので、SPも保持できます。したがって、これらの「Foo」クラスをORMに置き換えてそこから進むことをお勧めします。 SPの交換はお勧めしません。

PS。コードビハインドクラスには多くの共通コードがあり、それ自体がデザインパターンになっているようです。そもそもデザインパターンは何だと思いますか! (OK、それは最高ではないかもしれませんし、良いものではないかもしれませんが、それでもDPです)

編集: Dapper を使用して、ヘビーウェイトORMでsprocを回避する理由がなくなりました。

20
gbjbaanb

あなたはチームをある極端なもの(ストアドプロシージャとデータセット)から別の極端なもの(本格的なORM)に導こうとしているようです。データアクセスレイヤーのコード品質を向上させるために実装について設定できる他の段階的な変更は他にもあると思います。これは、チームがより進んで受け入れる可能性があります。

投稿した中途半端なアクティブレコード実装コードは特に重要ではありません。理解と実装が簡単で、.NET開発者に非常に人気のあるリポジトリパターンを調査することをお勧めします。このパターンは多くの場合ORMに関連付けられていますが、プレーンなADO.NETを使用してリポジトリを作成するのと同じくらい簡単です。

DataSetについて-残念!静的に(または動的に)型付けされたオブジェクトを返すと、クラスライブラリの操作がはるかに簡単になります。私は信じています この図 は、DataSetの私の意見が私よりも優れていることを説明しています。

また、ORMにジャンプせずにストアドプロシージャを破棄することもできます。パラメータ化されたSQLの使用には何の問題もありません。実際、サーバーへの複数のラウンドトリップを節約する複雑な手順がない限り、ストアドプロシージャを使用するよりも間違いなくそれを優先します。レガシーデータベースを開いてCRUDプロシージャの無限のリストを見ると、私もそれを嫌っています。

私はORMの使用を思いとどまらせていません。私は通常、私が取り組んでいるほとんどのプロジェクトでそれらを使用しています。しかし、なぜこのプロジェクトに導入しようとするのに十分な摩擦があるのか​​、そしてあなたのチームが親切に言うと、彼らが約8年前に新しいことを学ぶのをやめたように思えるかもしれません。私は間違いなく Dapper (このサイトに電力を供給するために使用されます)や Massive などの新しい種類の「マイクロORM」を見てみましょう。は非常に使いやすく、通常のORMよりもSQLに近づきやすく、チームはこれを受け入れたいと考えています。

13
richeym

私も同じような状況にありますが、実際にはハードウェア、能力、および政治がデータベース側に依存しているため、すべてがストアドプロシージャを通過します。残念ながら、特にメタデータとコード生成に関しては、テーブルほどストアドプロシージャに豊富なメタデータがないため、コーダーにとって苦痛です。

いずれにしても、ストアドプロシージャを使用して、エレガントでクリーンなコードを作成できます。現在、すべてのストアドプロシージャを使用して自分でリポジトリパターンを実装しています。データリーダーからビジネスオブジェクトにマッピングする際は、FluentAdo.netの素晴らしいアイデアを参考にしてください。私はそのアイデアの一部を取り、それを私の自家製のソリューションに転用しました。

4
Justin

JFTR-私は控えめなPHP開発者ですが、これは主に政治的な問題のように聞こえます。

アプリを支える「腐敗」の規模を考えると、ベストプラクティスは別として-それを根絶するにはかなりのオーバーヘッドがあります。これは、書き換え領域に接しているように聞こえます。

あなたが提案する代替案がビジネスのコストを正当化するための利益をもたらすことを保証できますか?このベンチャーのROIはビジネスに売り込むのが難しいのではないかと思います。アプリが不安定な場合、または金銭的にオーバーホールのメリットを証明できる場合を除き、これは難しい場合があります。

ORMはSPROCSのonly代替ですか?本格的なORMとVanilla SQLの間には、いくつかの設計パターンがあります。おそらく、これらのSPROCSをDBから徐々にDBALに取り込むことでプロセスを開始できます。もちろん、これが時間の経過とともに自作のORMに成長する危険はありますが、目標に一歩近づくことができます。

3
sunwukung

SPから数年前にORMに切り替えました。

1つのケースでは、80のテーブルを更新する必要がありました。古い推定モデルでは、entlibとSPを使用してこれを80時間見積もっていました。私たちは10年にそれをしました:)

これにより、データアクセス層の開発に費やす時間を80%削減できました。

2
Shiraz Bhaiji