- - PR -
ASP.NETからデータベースへの重複登録エラーについて
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2003-09-02 21:35
みなさま、こんばんは。
SQLServer内のテーブルAにデータを追加・修正・削除するWEBフォームを ASP.NETで作ったのですが、追加ボタンを押した時、 「PRIMARY KEY 違反、制約 PK_テーブルA:オブジェクトテーブルA には 重複したキーは挿入できません。ステートメントは終了されました。」 というエラーが出ます。(エラーは出たり出なかったりします。) 1回ボタンを押すと何故かinsert文が2度実行されて、 2度目のinsertの実行時に上の重複エラーが出ているようでした。 IISのログを見ると、POST要求が2度出されていたようなので、 タイムアウト関係かと思ってIISの設定を調べましたが、 [CGI スクリプトのタイムアウト]⇒300秒に設定 ASPのスクリプトのタイムアウト⇒90秒 となっていました。 (ちなみに、WEBフォームからSql Serverへの接続には SqlConnectionを使用していますが、 Connect Timeoutは30にしてあります。) ところが、SQLプロファイラでトレースしたところ、 1度目のinsertと2度目のinsertは以下のように、1秒も置かずに実行されていました。 EventClass TextData starttime RPC:Completed exec sp_reset_connetcion 2003-09-02 19:06:23.640 ☆SQL:BatchCompleted insert into ///// 2003-09-02 19:06:23.640 RPC:Completed exec sp_reset_connetcion 2003-09-02 19:06:23.687 ☆SQL:BatchCompleted insert into ///// 2003-09-02 19:06:23.687 --------------------------------------------------------------- 開発環境:Windows2000、SQLServer2000、VisualStudio.NET、IIS5.0 使用言語:C# テーブルA:32フィールド IISもSQLServerも同じマシン内で使用しています。 --------------------------------------------------------------- 似たような事例がないかと検索をかけましたが見つかりませんでした。 同じような質問内容についてのURLや、ヒントだけでもよいので お教え頂けると助かります。 とても困っています、どうぞ宜しくお願いいたします。 | ||||
|
投稿日時: 2003-09-02 21:48
こんにちは。
前後のコードだけでも載せて頂けると、みなさんの解答も頂きやすいかと思います。 ※私に解答できる力があれば良いのですが・・・。 | ||||
|
投稿日時: 2003-09-03 10:00
お返事ありがとうございます!
失礼いたしました。以下が前後のコードです。 (接続文字列はConnectクラスから持ってきています。) string strsql; strsql = "insert into ...."//<insert文 //接続 Connect source = new Connect(); SqlConnection conn = new SqlConnection(source.connString); conn.Open(); SqlCommand cmd = new SqlCommand(strsql,conn); try { cmd.ExecuteNonQuery(); } catch(Exception er) { //エラーメッセージの表示 OutputAlert(er.Message); return; } finally { cmd.Dispose(); conn.Close(); } //完了メッセージの表示 OutputAlert("新規登録されました"); --------------------------------------------------------------------------------- public class Connect { public string connString; public Connect() { //初期値の設定 connString="User Id=sa;Pwd=saのパスワード;data source=SQLサーバー名;database=データベース名;Connect Timeout=30;"; } } -------------------------------------------------------------------------------- OutputAlertメソッド: //アラート出力メソッド private void OutputAlert(string msg) { //エラーメッセージに「'」が含まれる場合のエラー回避 //改行(\n,\r)を削除 string delap = ((msg.Replace("'","")).Replace("\n","")).Replace("\r",""); bodytag.Attributes.Add("OnLoad","alert('"+delap+"');"); return; } (aspxフォームのbodyタグのid属性に<body id="bodytag" runat="server">を記述し、 フォームのコードの冒頭で 「protected System.Web.UI.HtmlControls.HtmlGenericControl bodytag;」 と宣言しています。) | ||||
|
投稿日時: 2003-09-03 10:19
こんにちは。
このコードが2回実行されている、ということでしょうか。まず、それを確認してください。確認方法は、とりあえずブレークポイントを張って、1度目はそのままスルーしてみると。 それとは別に、IDをどのようにして決めているのでしょうか。ASP.NETですよね?複数の人が同時にアクセスする可能性がありますよ?そのときに、同じIDが割り当たる危険性はないでしょうか。「同時に」というところに注意してください。 | ||||
|
投稿日時: 2003-09-04 11:53
レスどうもありがとうございます。
デバッグしたところ、このコード自体が二度実行されていました。 IDとはSQLサーバーへの接続文字列のことでしょうか? 初めWindows認証を使用していたのですが、 本番環境でうまくいかなかったので(<IISとSQLServerが別ドメインだったため) SQLサーバー認証のIDとパスワードで接続することにしました。 ユーザーはSessionIDを使って区別しているつもりでした。。 (Web.Configファイルに次のように記述しています。) <sessionState mode="InProc" stateConnectionString="tcpip=IPアドレス:ポート" cookieless="true" timeout="20"/> | ||||
|
投稿日時: 2003-09-04 12:07
では、デバッグ時に「呼び出し履歴」を表示して、1度目と2度目が、どこから呼ばれているかを確認します。呼び出し履歴をたどりながら、コーディングミスがないか確認してください。 IDは、データベースへ登録するデータのIDです。IDの重複ということなので、尋ねてみました。IDは、ユーザが振るのでしょうか。それともシステムで振るのでしょうか。ユーザが振るのであれば、ユーザはどのようにして指定したIDがユニークであることを判別しますか?システムが振るのであれば、どのタイミングでユニークであるIDを取得しますか?SQL Serverであれば、AutoNumberが使えますから、IDにこれを使っていればエラーは起こらず、この質問は「同じデータが2回登録されます」というものになったはずですよね。 | ||||
|
投稿日時: 2003-09-04 14:50
ありがとうございます。
一度目のコードは、 system.web.dll!System.Web.UI.HtmlControls.HtmlButton:nServerClick(System.eventArgs) から呼び出されていましたが、 二度目のコードはどこからも呼ばれず勝手に始まっているようです。 (一度目と二度目ではスレッド番号が違っていました。) 一度だけで終了しエラーが出ずに「新規登録」ダイアログが表示される場合も あるので、コード自体に誤りはないと思うのですが。。 主キーだけで登録するとすんなりいく(エラーがでない)のですが、 フィールドを沢山埋めて登録ボタンを押すとこのエラーが出るみたいなのです。 すみません、IDとは主キーのことだったのですね。 テーブル内の3つのフィールドをIDにしています。 | ||||
|
投稿日時: 2003-09-04 16:22
1度目は、OnServerClickからということは、正常なんですよね?
2度目・・・呼出元がいない???そんな、勝手に始まるなんてことがあったら怖すぎです。イベント登録しているとか、ないですか?外部ツールでGREPするとか、VS.NETのIDEで検索するときに「非表示のテキストを検索」をチェック、「現在のプロジェクト」から検索するようにして、もう一度呼び出している箇所がないか、チェックしてください。もしくは、1度目止めてからステップ実行してみてください。 それと、適切に環境が設定してあれば(ローカルホストならデフォルトで)Webページにエラーメッセージが表示され、そこにも呼び出し履歴が表示されると思いますが、それはどうですか? |