ストアドプロシージャの代わりにORMの使用を提案するにはどうすればよいですか?


31

私は、すべてのデータアクセスにストアドプロシージャのみを使用している会社で働いています。そのため、新しいプロシージャを実行する必要があるコミットごとにローカルデータベースの同期を維持するのは非常に面倒です。私は過去にいくつかの基本的な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が適切なアプローチであるかどうかはわかりません(ストアドプロシージャとDataSetにあまりにも多く投資しています)。それが正しい選択である場合、それを使用するケースをどのように提示すればよいですか?私の頭の一番上で考えられる唯一の利点は、よりきれいなコードを持っていることです(そうではないかもしれませんが、現在のアーキテクチャは ORMを念頭に置いて構築されているため、基本的に将来のモジュールにORMを審査しますが、古いモジュールは引き続きDataSetsを使用します)実行されたプロシージャスクリプトと実行する必要のあるスクリプトを覚える手間が少なくなります。など。しかし、それだけであり、どのように説得力があるかはわかりません。保守性も別の懸念事項ですが、私以外の誰も心配していないようです。


8
チームにORMを使用するように説得するだけでなく、問題があるように聞こえます。あなたのチームは、いくつかの優れた開発プラクティス(つまり、デザインパターン、ユニットテスト)を認識していないようです。これらは、取り組む必要があるより重要な問題です。
バーナード

6
皮肉なことに、私は約5年間の開発で、デザインパターンや単体テストなどを知っている少数の人々/チームにしか会ったことがないと思います。通常、私はこれらのことを知っている会社で唯一の男です。
ウェインモリナ

3
@ウェインM:私はそれが少し気になると思うが、これにも驚かない。
バーナード

2
私はそれをとても見つけました...落胆させます。あなたが何かを提案し、あなたが話していることや他の誰かがそれを行うことを検討する理由があいまいな考えを他の人が知らないことを示す「ヘッドライトの中の鹿」の外観を得るのは奇妙です。私は過去に何度かそれを経験しました。
ウェインモリナ

2
私はストアドプロシージャの大ファンなので、私のコメントには偏りがありますが、前提全体には完全に同意しません。あなたはORMが好きで、これを使用したいのです。ただし、チームの他のメンバーはストアドプロシージャで問題ありません。なぜあなたが好きなようにそれらを強制しますか?
ダークナイト

回答:


47

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

[通常、高速化は、クライアントおよびストアドプロシージャインターフェイスの設計方法と、トランザクションが短い集中的なSQLバーストとして書き込まれる方法が原因です。]

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

[多くの多くの人々がストアドプロシージャには魔法の力があり、それが引き起こす問題にもかかわらず使用しなければならないと感じているため、この質問は約-30のスコアを得るためにダウン投票されます。]

すべてのストアドプロシージャコードをクライアントに移動すると、すべての人にとって物事がずっと簡単になります。

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

これらのすべてのストアドプロシージャを書き換えると、テスト、修正、保守、理解、および適応が可能になります。アプリはほぼ同じように動作し、2つの異なるテクノロジーに分割されなくなったため、脆弱性が大幅に低下します。

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

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

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


19
+1ストアドプロシージャを扱うのは非常に苦痛だからです
ゲイリーロウ

3
: '(ストアドプロシージャに問題はありません。それは、私にとって単なる抽象化レイヤーです。
Mike Weller

3
SPを作成すると、データベースエンジンはそれをコンパイル済みフォームとして保存し、実行パスを作成して、可能な限り高速に実行されるようにします。しかし、ORMはデータベースエンジンでコンパイルして実行する必要があるたびにSQLを送信します。ストアドプロシージャの代わりにORMを使用すると時間がかかると思います。
DeveloperArnab 14年

4
おかしい。速度が理由で、ORMからストアドプロシージャに戻りました。プログラミングに必要な時間ではなく、ORMがオブジェクトの実体化、オブジェクトの検索、さまざまなクライアントでの更新などに必要な時間です。SPのほうがずっと速い。1つの例:新しいモダンなORMニーズでDBから30.000オブジェクトを読み取る...まあ。2分後にタイムアウトします。ストアドプロシージャを呼び出して結果を取得する-2秒。はい-DBからcallignを大幅に削減するためのページングなどの多くのトリックが存在します-しかし、ORMを使用できるか、または
11

2
@DeveloperArnab:20年前にはそうだったかもしれませんが、最新のDBエンジンは非常に洗練されており、以前に実行されたクエリを認識して実行プランを再利用できます。最近の速度の違いはごくわずかであり、SPの追加の手間はほとんど保証されません。
-whatsisname

20

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

DBAがそこに座って「ああ、コミットするたびに、クライアントをもう一度プルダウンする必要があります。代わりにすべてのコードをDBフォームに移動する必要があります」と思います。

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

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

編集:そして今Dapperでは、ヘビーウェイトORMを超えるprocsを避ける理由はなくなりました。


3
+1、明らかな最初のステップは、ORMに移動し、それを使用して既存のストアドプロシージャの結果をオブジェクトにマッピングすることです。そのすべてのds.Tables[0].Rows[0]["FooName"].ToString()がらくたを取り除きます。マネージャーはストアドプロシージャが好きですか?彼はそれらを保持します。しかし、たとえばLINQ to SQLによって生成される何かに、その反復的な定型コードをすべて移動することは悪いことだと主張することは物理的に不可能です。
Carson63000

11
さて、あなたの投稿にどれだけ「間違った」ものがあるのか​​信じられません。コードをプルする必要があると言っているDBAとの比較は不適切であり、まったく無意味です。まず第一に、データベースはデータの保存と取得を目的としたサービスであり、ストーリーの終わりです。名前が示すとおり、LOGICは、APIコードの一部であるビジネスロジック層に入ります。アプリはsprocsから離れてより壊れやすいですか?あなたは真剣ですか、それともただトローリングですか?TDDでsprocのロジックを使用してアプリを作成し、それがどれだけ楽しいかを教えてください。また、ORMは切り替えられることを意図していません。データベースは単なるサービスであるためです。
マッテオモスカ

5
データベースがすべてが神聖な神聖な土地であると考える人がいる理由を本当に理解することはできません。これについて考えます。サードパーティの会社があなたにサービスを公開するとき、彼らはあなたに彼らのデータベースへの直接アクセスを与えますか、それともAPIの背後にそれを隠しますか?人気のある例を使用するには、Googleサービスを利用してください。開発者は、公開APIに接続しますが、その下にどのデータベースがあるのか​​、またはデータベースがあるのか​​どうかさえわかりません。これが、堅牢で分離されたソフトウェアを設計する方法です。データベースは、アプリケーションから直接アクセスするためのものではありません。そのために中間層があります。
マッテオモスカ

5
@Matteo Mosca:確かですが、ミドルウェアはどのようにDBにアクセスしますか...それはDBのクライアントです。「クライアント」は「GUI」または「デスクトップアプリ」を意味しません。アプリケーション層には多くの灰色の領域があります-GUIまたはサーバー/ビジネスロジックに検証を配置しますか?きれいなデザインにするためにサーバーに配置する必要がありますが、それはパフォーマンスとユーザーの応答性にとって非常に悪いでしょう。同様に、パフォーマンスと(この場合)データの正確性が向上する場合、DBにロジックを配置することがよくあります。
gbjbaanb

4
申し訳ありませんが、私はまだ同意しません。使用したのと同じDBテクノロジーがない別の環境にアプリケーションをデプロイする必要がある日は、新しいデータベースにすべてのsprocがないためにアプリを実行できない状況に陥ります..また、SQLダイアレクトなどの違いにより、それらを再作成しても(これは非常に苦痛です)、標準(SOAPやRESTなど)で公開されるロジックと検証を備えた集中型APIがこれを解決します。問題、およびテスト容易性、バージョン管理、一貫性を追加します。
マッテオモスカ

13

チームをある極端(ストアドプロシージャとデータセット)から別の極端(本格的なORM)に導こうとしているようです。データアクセスレイヤーのコード品質を改善するために、実装に関して設定できるその他の追加の変更があると思いますが、チームはそれを喜んで受け入れます。

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

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

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

ORMの使用を推奨しているわけではありません。通常、私が取り組んでいるほとんどのプロジェクトでORMを使用しています。しかし、なぜこのプロジェクトとあなたのチームにそれを紹介しようとするのに多くの摩擦があるのか​​、私は見ることができます。8年前に新しいことを学ぶのをやめたように聞こえます。Dapper(このサイトを動かすために使用されます)やMassiveなど、「Micro ORM」の新しい種類を間違いなく見ていきます。典型的なORMはそうであり、あなたのチームはより喜んで受け入れるかもしれません。


2
この問題は、アプリが記述されたときに、.NETの実際のORMがなかったため、別の方法(ASP.NET 1.1の方法)で行われたと思います。数ヶ月前に参加するまで。
ウェインモリナ

1
Dapperの+1。プロジェクトで使用し始めたばかりで、実装と使用が非常に簡単です。私はすでに大ファンです。
SLoret

4

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

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


3

JFTR-私はあまりPHPを開発していませんが、これは主に政治的な問題のようです。

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

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

ORMがSPROCS の唯一の代替手段ですか?完全なORMとバニラSQLの間には、いくつかの設計パターンがあります。おそらく、これらのSPROCSを徐々にDBからDBALに入れることでプロセスを開始できます。もちろん、これがやがて自作ORMに成長する危険性がありますが、目標に一歩近づいているでしょう。


2

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

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

これにより、データアクセスレイヤーの開発に使用する時間が80%短縮されました。


1
そして、なぜテーブル更新をスクリプト化できなかったのですか?
ダークナイト

これは、メモリ内の複雑なオブジェクトを取得し、レポート用にリレーショナルデータベースとして保存していました。オブジェクトを反映してテーブル構造を作成するプログラムを作成しました。
シラーズバジー

-1

根本的な問題は、展開が適切かつ自動的に機能していないことです。

各コミット後に必要に応じてデータベースを操作する方法を知っている連続ビルドエンジンをセットアップする方が簡単な場合があります。

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