none
再び「同時実行違反」について RRS feed

  • 質問

  • お世話になっています。
    解決したと思ったのですが・・・。

    多くのデータを入力していると,ときどき「同時実行違反」のエラーになってしまいます。

    入力の途中にこまめに更新をしているのですが,何回か成功するうちにエラーになってしまいます。

    何が原因なのか特定できず,悩んでいます。

     

    2006年9月4日 13:55

すべての返信

  • 前のスレの続きになりますが、空白とかそういう問題じゃないない気がします。データ更新部分をどのように作成されているのかわからないのですが、もう一度DataAdapterの部分を作り直してみられたらいかがでしょうか?
    ちなみにmdbをSqlDataAdapterを通してDataTableをDataGridViewにバインドするテストコードを書いてみましたが、特に同時実行違反が起こることはありません。
    同時実行違反が起こる心配がないのであれば、DataAdapterの構成ウィザードで、オプティミスティック同時実行制御にチェックをつけなければいいだけですが、できればこうせずに解決したいところですよね。単なる意地ですが。(^^;

    #もしくは.NET2.0的にTableAdapterを使ってみてもいいかもしれません。

    2006年9月4日 14:32
    モデレータ
  • MDB だから OleDbDataAdapter では?
    それはさておき、オプティミスティックス同時実行制御の SQL は許容できますか?
    私は論外だと思っています。
    データの件数が少なければ、別にどうってことないですが、件数が多ければ Update するときにとんでもなくコストを払うことになります。
    MDB には GUID や TIMESTAMP が無いので、ロジック的にコントロールすることになると思いますが、できれば SQL Server 2005 Express (将来的には MDB に変わる機構が提供される予定)を使ったほうが良いように思いますが。
    2006年9月4日 15:46
  •  おがわみつぎ さんからの引用
    MDB だから OleDbDataAdapter では?

    すみません。OleDbDataAdapterの書き間違えでした。m(_ _)m
    その他の同時実行制御などについては、私も全面的にそう思います。
    それに本当に同時実行制御が必要ならば、複数のユーザーが同時に使うことが想定されるわけで、そうなれば規模にもよりますが、MDBでは力不足でしょう。であれば、今からSQL Server 2005 Expressを使っておけば、簡単にSQL Server 2005を使った本格的なクラサバシステムへ移行することもできるので、こちらを使われる方がお勧めだと思います。

    #でも、MDBで今回の障害の原因を突き止めることも、大事な勉強だと思いますので、今すぐにMDBをやめた方がいいという意味ではありません。時間が許せばですが。

    2006年9月5日 1:09
    モデレータ
  •  trapemiya さんからの引用
    SQL Server 2005 Expressを使っておけば、簡単にSQL Server 2005を使った本格的なクラサバシステムへ移行することもできるので、こちらを使われる方がお勧めだと思います。

    Management Studioを使ってSQL Server 2005 Expressのデータベースを作りました。
    SQL Server 2005 Expressを使うのは初めてです。C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Dataに作ったデータベースがあるようです。ファイルの種類は「SQL Server Database Primary Data File」となっております。
    これをコピーしてVSのプロジェクトファイルを格納してあるフォルダに移動させると,「ファイルのコピーエラー」になってしまいます。

    コピーするためには,何か別の操作が必要なのでしょうか?。お教え願います。


     

     

    2006年9月5日 3:20
  • とりあえず行き当たりばったりにmdbの常識を持ち込もうとしても出来ません。

    SQL Server 2005での開発といった1から教えてくれる書籍があるかどうかわかりませんが、腰をすえて勉強しましょう。

    2006年9月5日 3:35
  • 「ひと目でわかるMicrosoft SQL Server 2005」

    「SQL Server 2005ではじめよう データベースシステム開発入門」

    辺りが出版されているようです。


    #「SQL Server2000でいってみよう」

    は、SQL Server 2000を対象にした内容ですが、SQL Serverというデータベースに関して、大変わかりやすく簡潔にまとまっていますので、SQL Server 2005を学ぶ上でも大いに役立つと思います。お勧めです。


     zen73 さんからの引用

    これをコピーしてVSのプロジェクトファイルを格納してあるフォルダに移動させると,「ファイルのコピーエラー」になってしまいます。

    コピーするためには,何か別の操作が必要なのでしょうか?。お教え願います。


    コピーや移動をする必要はありません。そのまま、アプリケーションやVS2005から接続しにいきます。
    他のコンピュータへ持っていく時には、他のコンピュータにもSQL Server 2005 Expressがインストールされている必要があり、それに持っていったデータベースファイル(.mdf ファイル)がアタッチされる形になります。この辺りはまだMDBのような手軽さはありません。

    2006年9月5日 4:30
    モデレータ
  • エラーと関係するかはわかりませんが,
    JETデータベースの場合,文字列は,可変長文字列のみなので,
    固定長文字列と違って,後続のスペースは無視するので

    System.Data.OleDb.OleDbType.WChar

    でなく,

    System.Data.OleDb.OleDbType.VarWChar

    の方が無難なような気がします。

    2006年9月5日 19:53
  • SQL Server 2005 Express は,サービスとして動いているので,
    Accessユーザーにしてみると,微妙に使いづらいかもしれませんね。

    JETデータベースエンジンは,いわゆる DLL なので,
    アプリケーション・プロセスにロードされて使われるので,
    使っていない時は,MDBファイルも使っていない時になるわけです。

    一方,SQL Server 2005 Express は,
    デフォルトの状態でそのままインストールすると,
    SQL Server のサービスが自動起動するように構成されるので,
    データベースがSQL Server のインスタンスに登録されていれば,
    すでに起動しているので使用中になっているということですね。

    管理ツール -> サービス -> SQL Server (SQLEXPRESS) のところを
    右クリック -> プロパティ
    で,スタートアップの種類 が 自動 になっているのを確認できると思います。
    サービスとして動いているSQL Serverを止めれば,
    使用中ではなくなるのでコピーはできるようになります。

    でも,.mdfデータファイルごとコピーするのなら,
    ふつうは,上で出てきているように デタッチしてからです。

    デタッチは,
    SQL Server Management Studio Express でも,GUIで楽できた筈です。
    (データベース名を右クリック -> タスク -> デタッチ... )

    一度,データファイルをデタッチしておけば,
    上のテクニックでJETっぽく使えますね。

     

    # JETっぽくでなく,さらにJETらしい使い方というか,
    # サービスでなくDLL版?のもの(SQL Server Everywhere)がもうじき?出るそうですし,
    # ローカルのデータをSQL Serverで利用するのも,選択肢が増えて,
    # 小回りがきくようになるでしょう。
    # スタンドアロンでは,それの方を気に入る人が多いような気がします。

     

    2006年9月5日 20:10
  • お早うございます。皆さんから多くのアドバイスをいただきありがとうございます。
    今「名簿データ」を作っているところです。
    明日,白内障の手術をしますので報告は遅くなると思いますが,エラー「同時実行違反」解消の報告ができたらいいなと思ってます。

     

    2006年9月5日 20:41
  • UpdateCommandをTableAdapterのプロパティで設定しようとしていますがうまくいきません。近所の本屋に紹介いただいた本が全てありましたので目を通してみましたがこれに関する記述はどれにもありませんでした。ネットでも検索できないし,お手上げ状態です。

    更新したいのは,T_学力テーブルの国語~平均です。なおT_学力テーブルにはキーは設定していません。

    甘えてばかりですが,UpdateCommandのかきかたを教えていただけないでしょうか?

    SELECT    T_学力.ID, T_学力.学年, T_学力.回数, T_名簿.年, T_名簿.組,
                      T_名簿.NO, T_名簿.氏名, T_学力.国語, T_学力.数学, T_学力.社会,
                      T_学力.理科, T_学力.英語, T_学力.合計, T_学力.平均
    FROM       T_学力 INNER JOIN  T_名簿 ON T_学力.ID = T_名簿.ID
    ORDER BY     T_名簿.NO

    2006年9月6日 10:57
  • キーを設定してください。

    UPDATE T_学力
    SET 学年 = xx
    WHERE キー = 1

    2つのテーブルに更新したいときにはトランザクション制御してください。

    SQLの最初から教えている書籍であれば確実に書いてあります。がんばってください。

    2006年9月6日 12:04
  •  中博俊 さんからの引用
    キーを設定してください。

    [ID]  [学年] [回数] [国語]・・・・[英語] [合計] [平均]
    1101   1       1    80           70        400     80
    1101    1            2          70           90        390     78
    1101    1            3          75           85        410     82
    1101    2            1          90           75        420     84
    というように,IDを個人の識別番号としてテストデータを蓄積していこうと思っているのですが,キーを設定するとIDの重複は許されないのではないでしょうか。それともこのようなきーを設定しないテーブルは設計ミスということになるのでしょうか。

     

    2006年9月6日 13:38
  • これでキーを作成するなら

    ID, 学年, 回数でユニークですよね?

    それがPrimaryKeyたりえます。

    2006年9月6日 14:07
  •  zen73 さんからの引用

    [ID]  [学年] [回数] [国語]・・・・[英語] [合計] [平均]
    1101   1       1    80           70        400     80
    1101    1            2          70           90        390     78
    1101    1            3          75           85        410     82
    1101    2            1          90           75        420     84
    というように,IDを個人の識別番号としてテストデータを蓄積していこうと思っているのですが,キーを設定するとIDの重複は許されないのではないでしょうか。それともこのようなきーを設定しないテーブルは設計ミスということになるのでしょうか。

    このようなケースでは必要ないです。しかし、レコードを一意に識別するために、このテーブルのID値を付ける場合も無くはありません。

    [ID1]    [ID]  [学年] [回数] [国語]・・・・[英語] [合計] [平均]
        1     1101   1       1    80           70        400     80
        2     1101    1            2          70           90        390     78
        3     1101    1            3          75           85        410     82
        4     1101    2            1          90           75        420     84

     zen73 さんからの引用

    UpdateCommandをTableAdapterのプロパティで設定しようとしていますがうまくいきません。

    TableAdapterのUpdateCommandやSelectCommandなど全てのCommand系オブジェクトは、直接いじれないようになっています。TableAdapterという枠組みの中で、ウィザードによって内部的に生成されたこれらのDataAdapterのCommand系オブジェクトを、勝手にいじられては困るということなのかもしれません。

    それはさておき、単にUpdate文を使うだけでしたら、SqlCommandでUpdate文を発行すれば良いと思いますが、TableAdapterで行いたい場合には、次の手順になります。

    1.データからデータソースの表示をクリック。
    2.データソースの画面で右クリックして、新しいデータソースの追加。
    3.データベースを選らんで次へ。新しい接続で接続を作成して次へ。
    4.データセット内に指定するデータベースオブジェクトはとりあえずどこにもチェックを付けずに完了。ワーニングが出ますが、そのままはいを選んで続行。
    これでデータソース画面に型付けされたデータセットができました。
    5.データソース画面でそのデータセットを選択し、右クリックして、デザイナでDataSetを編集をクリック。
    6.グレーの横じまだらけの画面が出ます。そこで右クリックして、追加でQueryを選択。
    7.データ接続を選んで次へ。とりあえずSQLステートメントを使用するを選択して次へ。(ここで私は通常、新しいストアドプロシージャの作成を選びますが)
    8.UPDATEを選択して次へ。
    9.クエリビルダを起動します。右クリックしてテーブルを追加。
    10.UPDATE TABLE1 SET TEST1=@TEST1, TEST2=@TEST2 WHERE TESTID=@TESTID
    のような感じでSQL文を作成して次へ。
    11.関数名を指定して次へでUpdate文が生成される。
    12.ここで一度アプリケーションをビルド。
    13.上のビルドによって、ツールボックスに上で作成されてTableAdapterが追加されていますので、それをフォームにドラッグ。(デフォでQueriesTableAapter)
    14.あとはコードでqueriesTableAapter1.上で付けた関数名(パラメータ1, パラメータ2, ・・・)

    ただ、2つ以上のテーブルを同時にセットで更新となると、上のパターンではダメです。トランザクションを切って、SqlCommandで2つのテーブルを更新するか、2つのテーブルをトランザクションを切って一度に更新するストアドプロシージャを作成して、それをTableAdapterで使うというような感じになると思います。

    # 手術大変ですね。がんばって下さい。

     

    2006年9月6日 14:10
    モデレータ
  •  trapemiya さんからの引用

    このようなケースでは必要ないです。しかし、レコードを一意に識別するために、このテーブルのID値を付ける場合も無くはありません。

    中さんから突っ込まれそうなんで、フォローしときます。(^^; 必要ないとは絶対にキーを設けるなという意味ではありません。

    #さっき編集してたらまた???になって、その投稿を削除した時に子が居ますって言われて、えっ?と思ったんですが、中さんの投稿をひょっとして消しちゃいました。もし、そうならごめんなさい。m(_ _)m

    #長い文章を編集して???に変わるのは痛い。早く、直してほしいなぁ。

    2006年9月6日 14:20
    モデレータ
  •  trapemiya さんからの引用

    ただ、2つ以上のテーブルを同時にセットで更新となると、上のパターンではダメです。トランザクションを切って、SqlCommandで2つのテーブルを更新するか、2つのテーブルをトランザクションを切って一度に更新するストアドプロシージャを作成して、それをTableAdapterで使うというような感じになると思います。

    ざくっと調べてみたんですが、Transactionscopeの中で2つのテーブル更新をしてしまえばいいかな?
    もしくは、TableAdapterがpartialだから、そこにメソッド作って、その中でSqlTransactionを使って2つのテーブルを更新するという手もありそうですね。

    2006年9月6日 14:44
    モデレータ
  • 私の説明不足のところがありましたので
    2つのテーブル「T_名簿」「T_学力」を内部結合してdataGridViewに表示し,
    教科の点数を入力した後に,「T_学力」テーブルだけをdataGridViewのデータで更新したいのです。

    *それにしても,これからの道のりは私にとってあまりにもハードルが高くて,挑戦する気持ちを萎えさせてしまいがちです。愚痴になりますが,.mdbでは簡単に設定できたUpdateCommandがSQLServerではなぜにこうも複雑なのでしょうか。こんなにも難しいことが<SQLの最初から教えている書籍であれば確実に書いてあります>とは・・・・。すぐにでも同時実行違反を解消できるなどと思っていたのは浅はかでした。

     

    2006年9月6日 15:23
  • mdbでもSQL Serverでも、DataAdapterを使えば、一緒と言っても同じぐらい同じ手順ですし、TableAdapterを使ってもそうです。要は、DataAdapter, DataTable, SqlCommandの組で使うのか、それらを一まとめにして管理するTableAdapterを使うのかの違いです。mdbとSQL Serverの違いではありません。繰り返しになりますが、どちらを使っても同じようなコードになります。同時実行制御に関しても同じです。ただ、SQL Serverだとストアドプロシージャやトリガ、そういった素晴らしい機能を使うことができます。コーディングがほとんど同じなら、SQL Serverを使った方がいいとは思いませんか?

    T_学力を更新するのでしたら、OleCommandの代わりにSqlCommandを使うだけです。
    TableAdapterのウイザードを使えば、DataAdapterやSqlCommand、DataSet、DataTableなどの知識なしに、データベースが操作できるようになります。実は内部ではこれらが使われています。悪い言い方をすれば、これらADO.NETの知識なしに、簡単に初心者がデータベースを扱えるようにしたものとも言えます。
    DataAdapterの構成ウィザードを使ったとしても、そこから先はDataSetやDataTableの知識が要りましたよね。TableAdapterは、それをもっと進めたものだと思えばいいでしょう。
    なので、mdbだろがSQL Serverだろうが、接続先が違うだけで、TableAdapterの使い方に違いはありません。

    2006年9月6日 16:05
    モデレータ
  •  trapemiya さんからの引用
    それはさておき、単にUpdate文を使うだけでしたら、SqlCommandでUpdate文を発行すれば良いと思いますが、TableAdapterで行いたい場合には、次の手順になります。

    14.あとはコードでqueriesTableAapter1.上で付けた関数名(パラメータ1, パラメータ2, ・・・)


    いま,UpdateCommand追加のテストをしている所です。
       private void button1_Click(object sender, EventArgs e)
            {
                try
                {
                    int iRows = queriesTableAdapter1.UpdateQuery(  );
                    MessageBox.Show("Update " + iRows.ToString());
                }
                catch (Exception eUP)
                {
                    MessageBox.Show(eUP.Message);
                }
            }
    のところには,(string ID,string 国語, string 数学)とかくように促されていますが,何を書いたらいいのかわからないでいます。このことについてのアドバイスをお願いします。

    ---------テスト用のテーブル----------------
    SELECT        ID, 国語, 数学
    FROM           T_学力

    ---------追加したUodateCommand---------
    UPDATE       T_学力
    SET               ID = @ID, 国語 = @国語, 数学 = @数学
    WHERE       (ID = @ID) AND (国語 = @国語) AND (数学 = @数学)

    2006年9月9日 6:45
  • UpdateQueryというメソッドが自動生成されていますので、あとは

    queriesTableAdapter1.UpdateQuery(5, "90", "95");

    のように、順に、ID、国語の点、数学の点といれてあげればOKです。

    2006年9月9日 15:00
    モデレータ
  •  trapmiya さんからの引用

    queriesTableAdapter1.UpdateQuery(5, "90", "95");

    のように、順に、ID、国語の点、数学の点といれてあげればOKです。


    やはりそうでしたか。これでは私のやりたいこととは別のことになってしまうようです。

    《私のやりたいこと》はdataGridViewに入力した値で更新することなのです。

     

     

    2006年9月9日 19:21
  • 解決できました。

    .mdbに戻ってUpdateCommandについて検証してみました。
    列の一部だけを更新させていたのを,全ての列を更新するようにしてみた所「同時実行違反」が起こらないようになりました。

    絶対にとの確信はないのですが,まあ大丈夫かなと思ってます。

    多くの皆さんから親身なアドバイスをいただきましたとに感謝もうしあげます。ありがとうございました。

     

     

     

    2006年9月9日 21:09
  •  zen73 さんからの引用

    .mdbに戻ってUpdateCommandについて検証してみました。
    列の一部だけを更新させていたのを,全ての列を更新するようにしてみた所「同時実行違反」が起こらないようになりました。

    う~ん、直接関係ないような気がしますが、動いたんですね。あと、mdbの場合は、OleDBTypeから.NET Framework型との間に以下のような変換規則があるので、気をつけて下さい。mdbの日付時刻型はデフォルトでOleDb.OleDbType.DBDateに割り当てられますが、これだと日付部分しか持てないため、同時実行違反がおこる場合があります。この場合、OleDb.OleDbType.Date に変更すれば、時刻部分も含めて比較されますので、同時実行違反がおこりません。その他、以下の2つの表を見比べてみて下さい。 

    DataAdapter によるパラメータの使用
    http://msdn2.microsoft.com/ja-JP/library/bbw6zyha.aspx

    OleDbType 列挙体
    http://msdn2.microsoft.com/ja-JP/library/system.data.oledb.oledbtype.aspx

    2006年9月10日 3:06
    モデレータ
  • trapemiyaさんにはいつも懇切丁寧なアドバイスをいただき,ありがとうございます。
    年をとってくると,新しいこと(SQLServer)への取り組みがだんだんと億劫になってしまいます。
    これではいけないとは思っているのですが・・・。

    何とか動いていますので,今回はこれでいこうかなと思ってます。

    次回こそははSQL Serverでやってみようとおもってます。
    このようなフォローまでいただき,感謝のきもちでいっぱいです。

    2006年9月10日 21:21