19

Jobs というテーブルにデータを保存するアプリケーションがあります。Jobs テーブルには、UNIQUE 制約を持つ Name という列があります。Name 列は PRIMARY KEY ではありません。新しいエントリを保存/更新する前に自分でエントリの重複をチェックする必要があるのか​​ 、それともデータアクセスレイヤーによってスローされる例外を待つ方がよいのか疑問に思います. 重要な場合は、このアプリにNHibernateを使用しています


すばらしいインプットをしてくれたみんなに感謝します。

例外がスローされる (そしてコードによってキャッチされる) のを待つのではなく、コードで検証する必要があるもう 1 つの理由を見つけました。この場合、NHibernate は NHibernate.Exceptions.GenericADOException のみをスローするようです。これは、この場合の例外の原因に関してあまり有益ではありません。それとも、ここでNHibernateの側面が欠けていますか?

4

8 に答える 8

15

答えは、両方です。

データベースに制約がある場合、一意性など、データに関する特定の不変条件を保証できます。これはいくつかの点で役立ちます。

  • アプリケーションにバグがある場合、制約に違反すると、他の方法では気付かない可能性のある何かにフラグが立てられます。

  • データベースの他のユーザーは、DBMS が不変条件を適用するため、データの動作についてより多くのことを想定できます。

  • データベースは、制約に違反する不適切な更新から自身を保護します。他のシステムまたはインターフェイスがデータベースにデータを追加していることがわかった場合、データベースによって強制される制約は、制約によって捕捉されたものはシステムを壊さない (または少なくとも可能性が低い) ことを意味します。

アプリケーションとデータベースは、ほとんどの場合を除き、M:M の関係にあります。アプリケーションには適切なデータとビジネス ルールの検証が含まれている必要がありますが、アプリケーションがデータの唯一の顧客になるように計画する必要はありません。数年間データ ウェアハウスで作業すると、この考え方を持つ人々によって設計されたアプリケーションの効果がわかるでしょう。

于 2009-01-01T19:49:48.087 に答える
4

設計が (データベースと BL の両方で) 優れている場合、データベースには、BL で処理されないような制約があってはなりません。つまり、データベースに一貫性のないデータを提示するべきではありません。しかし、何も完璧ではありません。

データベースをデータ整合性の制約に限定することで、手続き型コードですべての BL 検証を処理できることがわかりました。また、データベースの例外が発生する唯一のケースは、修正できる (修正する必要がある) 設計エラーとコーディング エラーです。

あなたの場合、名前の一意性をチェックすることは、コードで適切に処理されるデータ コンテンツの検証です。これはおそらく、手数料のポイントに最も近いエラーをキャッチし、抽象化間の望ましくない結合を導入することなく、より使いやすい UI リソースを呼び出すことができることを願っています。

于 2009-01-01T22:59:22.213 に答える
3

その作業は完全にデータベースに任せます。コードは、例外をキャッチして適切に処理することに集中する必要があります。

理由:

  1. パフォーマンス- データベースは、高速かつ効率的な方法で制約を適用するために高度に最適化されます。コードを最適化する時間もありません。
  2. 保守性 - 将来制約が変更された場合、コードを変更する必要がないか、新しい catch{} を追加するだけで済みます。{} 制約が削除された場合、コードにまったく手を加える必要はありません。
于 2009-01-01T19:55:10.807 に答える
2

制約を自分で確認する場合は、データ アクセス レイヤーで行います。その層より上にあるものは、データベースやその制約について何も知らないはずです。

ほとんどの場合、DB から発生した例外をキャッチするために DAL に任せます。しかし、あなたの特定のケースでは、基本的な入力検証について話していると思います。フォーム全体を送信する前に、データベースへの名前の可用性チェック呼び出しを選択します。

于 2009-01-01T19:53:29.857 に答える
1

あなたが答える必要がある質問は次のとおりです:

「ユーザーに素敵なメッセージを提示する必要がありますか」。例:TestJob1という名前のジョブがすでに存在します。答えが「いいえ」の場合は、エラーをキャッチして一般的なメッセージを表示します。答えが「はい」の場合は、読み続けてください。

挿入後にエラーをキャッチした場合、正しいメッセージを表示するための十分な情報がありません(少なくとも不可知論的なDBの方法で)

一方、競合状態が発生する可能性があり、同じデータを挿入しようとする同時トランザクションが発生する可能性があるため、 DB制約が必要です。

うまく機能するアプローチは次のとおりです。

  • 素敵なメッセージを提示する前に確認してください
  • 例外をキャッチし、一般的なエラーメッセージを表示します(これはあまり頻繁に発生しないと想定しています)
于 2010-01-15T15:06:47.023 に答える
1

データ アクセス層によってスローされた例外を必ず確認する必要があります。同じ値を持つレコードがあるかどうかを確認する際の問題は、競合状態を防ぐために新しいレコードを挿入するまで、変更のためにテーブルをロックする必要があることです。

以前に自分ですべてを確認した場合でも、通常は例外/エラーを確認することをお勧めします。ほとんどの場合、問題が発生する可能性があるか、コードで考慮していないがデータベースによって強制されていることがあります。

編集:質問を正しく理解していれば、データベースによって制約を適用する必要があるかどうかではなく、アプリケーションコードでそれを処理する方法についてです。もちろん、データベースに不正なデータが入るのを防ぐために、データベース内のすべての制約を常に設定する必要があります。

于 2009-01-01T19:54:35.097 に答える
0

個人的には例外をキャッチします。これははるかに単純で、必要なコードがはるかに少なくなります。

于 2009-01-01T19:52:47.707 に答える
0

GenericADOException の内部例外は、データベース アクションが失敗した理由を示します。OracleException / MSSQLException / [InsertCustomExceptionHere] をキャッチし、そのメッセージからエラーを処理できます。これをフロントエンドに戻したい場合 (重複データを入力したのはユーザーであると仮定)、最初にカスタム例外でラップして、フロントエンドをデータベースに結合しないようにすることをお勧めします。RDBMS 固有の例外を渡したくありません。

挿入を行う前にデータベースの一意性をチェックすることに同意しません.データベースへの2回のラウンドトリップはあまり効率的ではなく、大量のユーザートラフィックがある場合は確かにスケーラブルではありません.

于 2009-04-16T15:49:43.167 に答える