2017-01-01 8 views
0

これをC#でプログラミングするには、最善の方法が必要です。私はレコードが存在するかどうかを確認しようとしています更新ステートメントelseステートメントを挿入、更新されたコードがまだ挿入/更新データベースに問題があります。このコードから実行後のデータベースには何も表示されません。レコードが存在する場合にヘルプが必要な場合その他の更新方法

 String updCmdTxt = "UPDATE.."; 
     String insertCmdTxt = "INSERT .."; 
     using (var scope = new TransactionScope()) 
     { 
      using (var con = new OracleConnection(strConnection)) 
      { 
       bool isDuplicate = false; 
       var insertcmd = new OracleCommand(insertCmdTxt, con); 
       try 
       { 


        con.Open(); 
          ......add params 

        insertcmd.ExecuteNonQuery(); 

        con.Close(); 
        Response.Redirect("test.aspx?Id=" + labelRID.Text); 
       } 
       catch (OracleException x) 
       { 
        isDuplicate = true; //determine if the exception is about duplicates. 
        if (!isDuplicate) 
        { 
         throw; 
        } 
       } 
       finally 
       { 
        insertcmd?.Dispose(); 
       } 
       if (isDuplicate) 
       { 
        using (var updcmd = new OracleCommand(updCmdTxt, con)) 

         { 

         .... 
         updcmd.ExecuteNonQuery(); 


        } 
       } 
       scope.Complete(); 
       Response.Redirect("test.aspx?Id=" + labelRID.Text); 

      } 
     } 
    } 

これをプログラムするには、より良い方法がありますか?

+0

2つのこと:1.あなたの 'rid'フィールドには一意制約があることを確認してください。 2.あなたの 'else'ブロック(' INSERT'オペレーション)で 'duplicate row exception'をキャッチして処理します。これらの問題は、最初のチェック「SELECT COUNT」と挿入/更新操作の間に別のクライアント/接続/スレッドが既に挿入を行った可能性がある場合に問題となります。 –

+0

最適化:カウントのチェックに使用した同じ接続を挿入または更新するために再利用することもできます。最後に挿入された行から自動インクリメントされたIDを取得する場合、別のスレッドで接続が使用されていないことを確認する必要があります。 –

+0

oracle merge文で希望することができます –

答えて

0

私がそれを達成するために使用するいくつかの一般的な技術がある何秒あたりの要求など、こうした重複の可能性として、すべての詳細を知らなくても助言を与えることは困難である:

  • ストアドプロシージャ'upsert'ワークフローをカプセル化します。 Oracle: how to UPSERT

  • はクライアント(あなたのケース)にアップサートロジックを実装いますが、開始トランザクションに必要な一貫性を保証し、あなたが操作を行った後、それを閉じるために参照してください。

テーブル内の既存の行の可能性が高い場合は、挿入前に更新を使用して頻繁な例外を回避します。そうしないと、更新前に挿入を使用してワークフローを最適化できます。

悲観的なソリューション

String updCmdTxt = "UPDATE ...."; 
String insertCmdTxt = "INSERT ...."; 
using (var scope = new TransactionScope()) 
{ 
    using (var con = new OracleConnection(conStr)){ 
     int rows; 
     using (var updcmd = new OracleCommand(updCmdTxt, con)){ 
     //Set parameters ... 
     rows = updcmd.ExecuteNonQuery(); 
     } 
     //If update command did not affect any rows, insert 
     if (rows == 0) { 
     using (var insertcmd = new OracleCommand(insertCmdTxt, con)){ 
      // Set parameters... 
      insertcmd.ExecuteNonQuery(); 
     } 
     } 
     scope.Complete(); 
    } 
} 

楽観ソリューション

String updCmdTxt = "UPDATE ...."; 
String insertCmdTxt = "INSERT ...."; 
using (var scope = new TransactionScope()) 
{ 
    using (var con = new OracleConnection(conStr)) 
    { 
     bool isDuplicate = false; 
     var insertcmd = new OracleCommand(insertCmdTxt, con); 
     try 
     { 
      // Set parameters... 
      insertcmd.ExecuteNonQuery(); 
     } 
     catch (OracleException x) 
     { 
      isDuplicate = ...; //determine if the exception is about duplicates. 
      if (!isDuplicate) 
      { 
       throw; 
      } 
     } 
     finally 
     { 
      insertcmd?.Dispose(); 
     } 
     if (isDuplicate) 
     { 
      using (var updcmd = new OracleCommand(updCmdTxt, con)) 
      { 
       //Set parameters ... 
       updcmd.ExecuteNonQuery(); 
      } 
     } 
     scope.Complete(); 
    } 
} 
+0

重複する限り私は重複を避けたいと思います。確率はそうではありません。それは私があなたにそれについて話すことができるほど最高です。 –

+0

私はすでにテーブルにあるレコードを挿入するという意味で重複を意味しました。私が提供した例では、重複や競合状態を避けることができます。 –

+0

これはうまくいくと思います。もう1つの質問。私はupdCmdTextにエラーを受け取ります: –

1

INSERTおよびUPDATE文の機能性を兼ね備えたMERGE文を使用します。例:

MERGE INTO CONTRACT_INFO c 
    USING (SELECT 12345 FROM DUAL AS RID) d 
    ON (d.RID = c.RID) 
    WHEN MATCHED THEN 
    UPDATE 
     SET CONTRACT_INFO_FIELD_1 = something, 
      CONTRACT_INFO_FIELD_2 = something_else 
    WHEN NOT MATCHED THEN 
    INSERT (RID, CONTRACT_INFO_FIELD_1, CONTRACT_INFO_FIELD_2) 
    VALUES (d.RID, something, something_else); 

+0

Oracleでは 'MERGE'は原子的な操作ですか?私はOracleを扱っていませんが、MSSQLではそれは原子ではありません。 –

+0

私はそれを疑いますが、他のDML文と同様に、それは処理されます。なぜあなたにとって重要なのですか? [あなたはこの答えをチェックしましたか?](http://stackoverflow.com/questions/4226830/can-i-do-an-atomic-merge-in-oracle) –

関連する問題