69

Q: SqlExceptionsを処理するためのより良い方法はありますか?

以下の例は、メッセージ内のテキストの解釈に依存しています。

例1:テーブルが存在しない場合に処理する既存のtrycatchがあります。
そもそもテーブルが存在するかどうかを確認できたという事実は無視してください。

try
{
    //code
}
catch(SqlException sqlEx)
{
        if (sqlEx.Message.StartsWith("Invalid object name"))
        {
            //code
        }
        else
            throw;
}

例2:重複キー例外を示すtrycatchなし

if (sqlEx.Message.StartsWith("Cannot insert duplicate key row in object"))

解決策:SqlExceptionHelperの開始

//-- to see list of error messages: select * from sys.messages where language_id = 1033 order by message_id
public static class SqlExceptionHelper
{
    //-- rule: Add error messages in numeric order and prefix the number above the method

    //-- 208: Invalid object name '%.*ls'.
    public static bool IsInvalidObjectName(SqlException sex)
    { return (sex.Number == 208); }

    //-- 2601: Cannot insert duplicate key row in object '%.*ls' with unique index '%.*ls'. The duplicate key value is %ls.
    public static bool IsDuplicateKey(SqlException sex)
    { return (sex.Number == 2601); }
}
4

9 に答える 9

147

SqlExceptionには、確認できるNumberプロパティがあります。重複エラーの場合、番号は2601です。

catch (SqlException e)
{
   switch (e.Number)
   {
      case 2601:
         // Do something.
         break;
      default:
         throw;
   }
 }

サーバーからすべてのSQLエラーのリストを取得するには、次のことを試してください。

 SELECT * FROM sysmessages

アップデート

これは、C#6.0で簡略化できるようになりました

catch (SqlException e) when (e.Number == 2601)
{
   // Do something.
}
于 2011-06-03T01:04:51.837 に答える
20

ある種、ある種。データベースエンジンエラーの原因と解決を参照してください

class SqllErrorNumbers
{ 
   public const int BadObject = 208;
   public const int DupKey = 2627;
}

try
{
   ...
}
catch(SqlException sex)
{
   foreach(SqlErrorCode err in sex.Errors)
   {
      switch (err.Number)
      {
      case SqlErrorNumber.BadObject:...
      case SqllErrorNumbers.DupKey: ...
      }
   }
}

ただし、問題は、例外処理やネストされたトランザクションなどのパターンを使用して、T-SQL(ストアドプロシージャ)TRY/CATCH に優れたDALレイヤーが存在することです。残念ながら、T-SQLブロックは元のエラーコードを発生させることができず、 50000を超えるコードで新しいエラーを発生させる必要があります。これにより、クライアント側で問題が処理されます。SQL Serverの次のバージョンには、T-SQLキャッチブロックから元の例外を再発生させることができる新しいTHROW構造があります。TRY/CATCH

于 2011-06-03T01:15:14.400 に答える
9

エラーコードを使用することをお勧めします。解析する必要はありません。

try
{
}
catch (SqlException exception)
{
    if (exception.Number == 208)
    {

    }
    else
        throw;
}

208を使用する必要があることを確認する方法:

select message_id
from sys.messages
where text like 'Invalid object name%'
于 2011-06-03T01:03:51.423 に答える
4

SQLサーバーで出会ったエラーメッセージのリストが必要な場合は、

SELECT *
FROM master.dbo.sysmessages
于 2012-06-21T13:04:12.733 に答える
2

重大度タイプに基づいて評価できます。これを使用するには、OnInfoMessageにサブスクライブする必要があることに注意してください

conn.InfoMessage += OnInfoMessage;
conn.FireInfoMessageEventOnUserErrors = true;

次に、OnInfoMessageには次のものが含まれます。

foreach(SqlError err in e.Errors) {
//Informational Errors
if (Between(Convert.ToInt16(err.Class), 0, 10, true)) {
    logger.Info(err.Message);
//Errors users can correct.
} else if (Between(Convert.ToInt16(err.Class), 11, 16, true)) {
    logger.Error(err.Message);
//Errors SysAdmin can correct.
} else if (Between(Convert.ToInt16(err.Class), 17, 19, true)) {
    logger.Error(err.Message);
//Fatal Errors 20+
} else {
    logger.Fatal(err.Message);
}}

このようにして、エラー数ではなく重大度を評価し、より効果的にすることができます。重大度の詳細については、こちらをご覧ください。

private static bool Between( int num, int lower, int upper, bool inclusive = false )
{
    return inclusive
        ? lower <= num && num <= upper
        : lower < num && num < upper;
}
于 2016-08-31T07:10:21.307 に答える
1

SQLExceptionを処理するためのより良い方法を探している場合は、いくつかの方法があります。まず、Spring.NETはあなたが探しているものと似たようなことをします(私は思います)。彼らがしていることへのリンクはここにあります:

http://springframework.net/docs/1.2.0/reference/html/dao.html

また、メッセージを見る代わりに、エラーコード(sqlEx.Number)を確認することもできます。これは、発生したエラーを特定するためのより良い方法のように思われます。唯一の問題は、返されるエラー番号がデータベースプロバイダーごとに異なる可能性があることです。プロバイダーを切り替える予定がある場合は、現在の方法で処理するか、この情報を変換する抽象化レイヤーを作成することに戻ります。

エラーコードと設定ファイルを使用して、ユーザーフレンドリーなエラーメッセージを翻訳およびローカライズした人の例を次に示します。

https://web.archive.org/web/20130731181042/http://weblogs.asp.net/guys/archive/2005/05/20/408142.aspx

于 2011-06-03T01:03:33.227 に答える
1

MS SQL 2008では、サポートされているエラーメッセージをテーブルsys.messagesに一覧表示できます。

SELECT * FROM sys.messages
于 2013-04-15T08:26:43.490 に答える
1

私は最初にコード、C#7およびエンティティフレームワーク6.0.0.0を使用しています。わたしにはできる

Add()
{
     bool isDuplicate = false;
     try
     {
       //add to database 
     }
     catch (DbUpdateException ex)
     {
       if (dbUpdateException.InnerException != null)
       {
          var sqlException = dbUpdateException.InnerException.InnerException as SqlException;
          if(sqlException != null)
             isDuplicate = IsDuplicate(sqlException);
       } 
     }
     catch (SqlException ex)
     {
        isDuplicate = IsDuplicate(ex);
     }  
     if(isDuplicate){
       //handle here
     }
}

bool IsDuplicate(SqlException sqlException)
{
    switch (sqlException.Number)
    {
        case 2627:
            return true;
        default:
            return false;
    }
}

注意:アイテムをdbに追加するためのクエリは、別のプロジェクト(レイヤー)にあります

于 2017-12-11T07:15:11.100 に答える
0

別のマシンからDBに接続するときに(たとえば、フォームの読み込み時に)SQLエラーをスローする可能性のある新人の場合、C#でSQLサーバーデータベースを指すデータテーブルを最初にセットアップすると、次のような接続がセットアップされます。

this.Table_nameTableAdapter.Fill(this.DatabaseNameDataSet.Table_name);

この行を削除して、MSDNなどで説明されている従来の接続文字列などに置き換える必要がある場合があります。

http://www.connectionstrings.com/sql-server-2008

于 2013-03-01T16:08:56.683 に答える