none
親子関係の DataGridView で「DBConcurrencyException はハンドルされませんでした」が出てしまう RRS feed

  • 質問

  • 親子関係にあるテーブルで同時に入力を行い、
    BindingNavigator の Save ボタンを押すと、
    両テーブルが保存されることを期待して、以下のようにしました。

     

    まず、ひらがな50音を使ったサンプルを作りました。
    columns テーブルの id は chars テーブルで column_id として使われています。
    両テーブルのリレーションシップは以下のように設定しています。

     

    - 確認画像 : columns と chars のリレーションシップ

     

    コード ブロック

    columns
    ------------------------------------------------
    id      INT             NOT NULL PRIMARYKEY <-------+
    name    VARCHAR(50)     NOT NULL                    |   
    ------------------------------------------------    |
                                                        |
    chars                                               |
    ------------------------------------------------    |
    id          INT             NOT NULL PRIMARYKEY     |
    column_id   INT             NOT NULL ---------------+ FOREIGNKEY
    name        VARCHAR(50)     NOT NULL
    ------------------------------------------------

     

    続いて、両 DataTable を Form にドラッグして DataGridView を作成。

     

    以上です。操作は以下の通りです。

     

    (1) columns の name に "あ" を入力

     

    (2) chars の name に "あ" を入力

     

    (3) columnsDataTable を Form にドラッグした時、DataGridView と一緒に追加された
        BindingNavigator の Save ボタンをクリック

     

    (4) "System.Data.DBConcurrencyException はハンドルされませんでした。" という例外発生 (以下参照)

     

    - 確認画像 : 保存直前
    - 確認画像 : 例外発生

     

    以上ですが、Save ボタンを押すと両テーブルとも保存されることを期待してい
    たのですが、そうはならない。これはどういう作りであるべきなのでしょうか?

     

    「同時実行違反」に関する質問は他の方もされていますが、今回、何が同時実
    行違反なのか、分かっていません。

     

    お分かりの方、お教え願えませんか?

    2008年1月7日 6:34

すべての返信

  • おそらく下記資料の処理を実装する必要があるのだろうと思い、やってみました。

     

    - チュートリアル : 同時実行例外の処理

     

    Customers を columns に変更して同じ作業をしたら、
    (2) で型が違うと言われたので、columns を全て chars に書き換えました。

     

    (1) のようにして tableAdapterManager.UpdateAll() を使いました。

     

    (3) は怪しい。
    FindByid() の引数として RowWithError.id を使うべきなのか、
    RowWithError.column_id を使うべきなのか分かっていない。

     

    (5) は、資料では custRow.Item(i, RowVersion) なのですが、Item なんて
    charRow には無い、と言われたので、 charRow[i, RowVersion] としました。

     

    コード ブロック

    public partial class Form4 : Form
    {
      public Form4()
      {
        InitializeComponent();
      }

     

      private void columnsBindingNavigatorSaveItem_Click(object sender, EventArgs e)
      {
        //this.Validate();
        //this.columnsBindingSource.EndEdit();
        //this.tableAdapterManager.UpdateAll(this.syllabaryDataSet);

        UpdateDatabase();
      }

     

      private void Form4_Load(object sender, EventArgs e)
      {
        this.charsTableAdapter.Fill(this.syllabaryDataSet.chars);
        this.columnsTableAdapter.Fill(this.syllabaryDataSet.columns);
      }

     

      private void UpdateDatabase()
      {
        try
        {
          //this.columnsTableAdapter.Update(this.syllabaryDataSet.columns);
          this.tableAdapterManager.UpdateAll(this.syllabaryDataSet); ............... (1)
          MessageBox.Show("Update successful");
        }
        catch (DBConcurrencyException dbcx)
        {
          DialogResult response = MessageBox.Show(
            CreateMessage((syllabaryDataSet.charsRow)(dbcx.Row)), .................. (2)
            "Concurrency Exception",
            MessageBoxButtons.YesNo);

     

          ProcessDialogResult(response);
        }
        catch (Exception ex)
        {
          MessageBox.Show(

            "An error was thrown while attempting to update the database.");
        }
      }

     

      private string CreateMessage(syllabaryDataSet.charsRow cr)
      {
        return
          "Database: " + GetRowData(GetCurrentRowInDB(cr), DataRowVersion.Default)

                       + "\n" +
          "Original: " + GetRowData(cr, DataRowVersion.Original) + "\n" +
          "Proposed: " + GetRowData(cr, DataRowVersion.Current) + "\n" +
          "Do you still want to update the database with the proposed value?";
      }

     

      private syllabaryDataSet.charsDataTable
        tempCharsDataTable = new syllabaryDataSet.charsDataTable();

     

      private syllabaryDataSet.charsRow GetCurrentRowInDB(

        syllabaryDataSet.charsRow RowWithError)
      {
        this.charsTableAdapter.Fill(tempCharsDataTable);
        syllabaryDataSet.charsRow
          currentRowInDb = tempCharsDataTable.FindByid(RowWithError.id); ........... (3)

        return currentRowInDb;
      }

     

      private string GetRowData(

        syllabaryDataSet.charsRow charRow,

        DataRowVersion RowVersion)
      {
        string rowData = "";

        for (int i = 0; i < charRow.ItemArray.Length; i++) ......................... (4)
        {
          rowData = rowData + charRow[i, RowVersion].ToString() + " "; ............. (5)
        }
        return rowData;
      }

     

      private void ProcessDialogResult(DialogResult response)
      {
        switch (response)
        {
          case DialogResult.Yes:
            UpdateDatabase();
            break;

          case DialogResult.No:
            syllabaryDataSet.Merge(tempCharsDataTable);
            MessageBox.Show("Update cancelled");
            break;
        }
      }
    }

     

    結果は、保存時に (4) の charRow が null で NullReferenceException が出ました。
    う~ん。

     

    コード ブロック

    System.NullReferenceException はハンドルされませんでした。
      Message="オブジェクト参照がオブジェクト インスタンスに設定されていません。"
      Source="saveUndeterminedParentIdAndChild"
      StackTrace:
        場所 saveUndeterminedParentIdAndChild.Form4.GetRowData(charsRow charRow, DataRowVersion RowVersion)
        場所 C:\Documents and Settings\custar\My Documents\Visual Studio 2008\Projects\saveUndeterminedParentIdAndChild\saveUndeterminedParentIdAndChild\Form4.cs:行 80
        場所 saveUndeterminedParentIdAndChild.Form4.CreateMessage(charsRow cr)
        場所 C:\Documents and Settings\custar\My Documents\Visual Studio 2008\Projects\saveUndeterminedParentIdAndChild\saveUndeterminedParentIdAndChild\Form4.cs:行 59
        場所 saveUndeterminedParentIdAndChild.Form4.UpdateDatabase()
        場所 C:\Documents and Settings\custar\My Documents\Visual Studio 2008\Projects\saveUndeterminedParentIdAndChild\saveUndeterminedParentIdAndChild\Form4.cs:行 44
        場所 saveUndeterminedParentIdAndChild.Form4.columnsBindingNavigatorSaveItem_Click(Object sender, EventArgs e)
        場所 C:\Documents and Settings\custar\My Documents\Visual Studio 2008\Projects\saveUndeterminedParentIdAndChild\saveUndeterminedParentIdAndChild\Form4.cs:行 25
        場所 System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
        場所 System.Windows.Forms.ToolStripButton.OnClick(EventArgs e)
        場所 System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
        場所 System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
        場所 System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
        場所 System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
        場所 System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
        場所 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
        場所 System.Windows.Forms.Control.WndProc(Message& m)
        場所 System.Windows.Forms.ScrollableControl.WndProc(Message& m)
        場所 System.Windows.Forms.ToolStrip.WndProc(Message& m)
        場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
        場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
        場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
        場所 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
        場所 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
        場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
        場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
        場所 System.Windows.Forms.Application.Run(Form mainForm)
        場所 saveUndeterminedParentIdAndChild.Program.Main()
        場所 C:\Documents and Settings\custar\My Documents\Visual Studio 2008\Projects\saveUndeterminedParentIdAndChild\saveUndeterminedParentIdAndChild\Program.cs:行 18
        場所 System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
        場所 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
        場所 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
        場所 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
        場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
        場所 System.Threading.ThreadHelper.ThreadStart()
      InnerException:

     

    2008年1月7日 7:17
  • - 確認画像 : columns と chars のリレーションシップ

     

    上記リレーションシップで設定していた「AcceptRejectRule の設定」を
    "Cascade" から "None" にすると、期待通りに保存された。

     

    でも、この設定を解除すると、両テーブルの変更を同時に元に戻せなくなるの
    で、困るんだけど.... 何とかならないですかねぇ?

    2008年1月7日 10:45