8

最近開発中のアプリでは、データベースへの挿入、更新、削除の影響を受ける行数を確認し、予期しない数の場合はエラーをログに記録しています。たとえば、1つの行の単純な挿入、更新、または削除で、ExecuteNonQuery()呼び出しから1つ以外の行が返された場合、エラーと見なしてログに記録します。また、これを入力すると、トランザクションが発生した場合にトランザクションをロールバックしようとさえしないことに気付きました。これはベストプラクティスではなく、確実に対処する必要があります。とにかく、これが私が何を意味するかを説明するためのコードです:

dbを呼び出すデータ層関数があります。

public static int DLInsert(Person person)
{
    Database db = DatabaseFactory.CreateDatabase("dbConnString");

    using (DbCommand dbCommand = db.GetStoredProcCommand("dbo.Insert_Person"))
    {
        db.AddInParameter(dbCommand, "@FirstName", DbType.Byte, person.FirstName);
        db.AddInParameter(dbCommand, "@LastName", DbType.String, person.LastName);
        db.AddInParameter(dbCommand, "@Address", DbType.Boolean, person.Address);

        return db.ExecuteNonQuery(dbCommand);
    }
}

次に、ビジネスレイヤーがデータレイヤー関数を呼び出します。

public static bool BLInsert(Person person)
{
    if (DLInsert(campusRating) != 1)
    {
        // log exception
        return false;
    }

    return true;
}

そして、コードビハインドまたはビュー(私はWebフォームとMVCプロジェクトの両方を行います):

if (BLInsert(person))
{
    // carry on as normal with whatever other code after successful insert
}
else
{
    // throw an exception that directs the user to one of my custom error pages
}

このタイプのコードを使用すればするほど、やり過ぎだと感じます。特にコードビハインド/ビューで。単純な挿入、更新、または削除では、データベース内の正しい行数が実際には変更されないと考える正当な理由はありますか?毎回影響を受ける行に対して単調なチェックを行うのではなく、実際のSqlExceptionをキャッチしてそれを処理することだけを心配する方が妥当ですか?

ありがとう。皆さんが私を助けてくれることを願っています。


アップデート

お時間を割いていただき、ありがとうございました。今後どの設定を使用するかはまだ100%決定していませんが、すべての回答から削除したものを次に示します。

  • DBライブラリと.Netライブラリを信頼してクエリを処理し、設計どおりに機能します。
  • ストアドプロシージャでトランザクションを使用して、エラーのクエリをロールバックし、raiseerrorそれらの例外をSqlExceptionとして.Netコードにスローバックするために使用する可能性があります。これにより、これらのエラーをtry/catchで処理できます。このアプローチは、問題のある戻りコードのチェックに取って代わります。

私が見逃している2番目の箇条書きに問題はありますか?

4

5 に答える 5

5

質問は「なんでこれをチェックするの?」になると思います。データベースがクエリを実行することを信頼していないという理由だけである場合、それはおそらくやり過ぎです。ただし、このチェックを実行する論理的な理由が存在する可能性があります。

たとえば、私はかつてこの方法を使用して並行性エラーをチェックした会社で働いていました。アプリケーションで編集するためにデータベースからレコードがフェッチされると、LastModifiedタイムスタンプが付いてきます。次に、データアクセス層の標準のCRUD操作には、レコードの変更されたカウントをWHERE LastMotified=@LastModified実行するときに句が含まれます。UPDATEレコードが更新されていない場合は、同時実行エラーが発生したと見なされます。

並行性チェック(特にエラーの性質を想定する部分)にはちょっと雑な感じがしましたが、それはビジネスのために仕事を成し遂げました。

あなたの例で私がもっと気になるのは、これがどのように達成されているかの構造です。1またはデータアクセスコードから返されるの0は「マジックナンバー」です。それは避けるべきです。実装の詳細がデータアクセスコードからビジネスロジックコードにリークしています。このチェックを引き続き使用する場合は、チェックをデータアクセスコードに移動し、失敗した場合は例外をスローすることをお勧めします。一般に、戻りコードは避ける必要があります。

編集:上記の最後のポイントに関連して、コードに潜在的に有害なバグがあることに気づきました。複数のレコードが変更された場合はどうなりますか?おそらくでは発生しませんが、INSERTで簡単に発生する可能性がありUPDATEます。コードの他の部分は、!= 1レコードが変更されていないことを意味すると想定する場合があります。それはデバッグを非常に問題にする可能性があります:)

于 2012-04-30T14:28:54.517 に答える
2

一方では、ほとんどの場合、すべてが期待どおりに動作する必要があり、その場合、追加のチェックによってアプリケーションに何も追加されません。一方、問題が発生した場合、それを知らないと、気付く前に問題が非常に大きくなる可能性があります。私の意見では、特に障害時にロールバックを実装する場合は、少しの追加の保護は少しの追加の努力の価値があります。それはあなたの車のエアバッグのようなものです...あなたが決して衝突しないならばそれは実際には目的を果たしません、しかしあなたがそうするならばそれはあなたの命を救うことができます。

于 2012-04-30T14:28:45.670 に答える
1

私は常にraiserror、カウントするよりもsprocで例外を処理することを好みました。このように、ロギング/監査などの他のことを行うためにsprocを更新する場合、行数をチェックすることを心配する必要はありません。

コードの2番目のチェックが好きな場合、または例外/を処理したくない場合でも、raiserrorチームは、データベース内のすべてのsprocに対してsprocの実行が成功すると0を返し、それ以外の場合は別の数値を返します。

于 2012-04-30T14:27:16.780 に答える
0

それは絶対にやり過ぎです。コアプラットフォーム(.Netライブラリ、SQL Server)が正しく機能することを信頼する必要があります-それについて心配する必要はありません。

ここで、トランザクションが正しくロールバックされているかどうかなど、テストする必要のある関連インスタンスがいくつかあります。

于 2012-04-30T14:29:20.190 に答える
0

そのチェックが必要な場合は、データベース自体の中でそのチェックを行ってみませんか?ラウンドトリップを行う必要がなく、より「集中化された」段階で実行されます。データベースをチェックインすると、そのデータベースにアクセスするすべてのアプリケーションから一貫して適用されていることが保証されます。一方、ロジックをUIに配置する場合は、その特定のデータベースにアクセスするUIアプリケーションが正しいロジックを適用し、それを一貫して実行することを確認する必要があります。

于 2012-04-30T14:34:45.190 に答える