none
UserControl 上の DataGridView に保存したデータが、アプリケーション再起動で消えるのは何故? RRS feed

  • 質問

  • mdf ファイルのデータテーブルを DataGridView として含む UserControl を作
    り、別の Form 上にその UserControl を載せてアプリケーションを作りました。
    図にすると以下のような感じです。

     

    +---------------------------+
    | Form                      |
    |                           |
    | +-----------------------+ |
    | | UserControl           | |
    | |                       | |
    | | +-------------------+ | |
    | | | DataGridView      | | |
    | | +---+---+---+---+---+ | |
    | | |   |   |   |   |   | | |
    | | +---+---+---+---+---+ | |
    | | |   |   (mdf)   |   | | |
    | | +---+---+---+---+---+ | |
    | | |   |   |   |   |   | | |
    | | +---+---+---+---+---+ | |
    | | |   |   |   |   |   | | |
    | | +---+---+---+---+---+ | |
    | +-----------------------+ |
    +---------------------------+

     

    アプリケーションを起動後、DataGridView にデータを入力して保存すると、ア
    プリケーション起動中は保存されているように見えるのですが、一旦閉じて、
    再起動させると DataGridView に保存していたはずのデータが空っぽになって
    しまいます。


    改めて入力と保存をすると、primary key だけは auto increment しています。
    同じく閉じて再起動後データを確認すると空っぽです。


    試しに、DataGridView を UserControl 上に作らず、直接 Form 上に置いた場
    合、保存したものが残っていることを確認しています。


    これは裏で何が起こっているのでしょう?


    UserControl を使った場合でもデータを残すにはどうしたらいいのでしょう?

     

     

     

    + 追記

     

    もしかして理由は、

     

    DataTable から Form にドラッグして作られた DataGridView の場合、
    自動的に Form_Load() 時に Fill() されますが、

     

    UserControl 上の DataGridView では、UserControl 作成時に、DataTable ド
    ラッグで UserControl_Load() 時に Fill() をしてくれるようなコードが自動
    的に書かれていないだけ?


    という訳で、

     


    Code Snippet
    Code Snippetprivate void UserControl1_Load(object sender, EventArgs e)
    {
      this.columnsTableAdapter.Fill(this.syllabaryDataSet.columns);
    }

     

     

    と手動で書けば、出ましたが、でも気になるメッセージが出てきました。

     


    Code Snippet
    Code Snippetファイル C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\syllabary.mdf
    の自動的に名前が付けられたデータベースをアタッチできませんでした。
    同じ名前のデータベースが既に存在するか、
    指定されたファイルを開けないか、
    UNC 共有に配置されています。

     

     


    このメッセージが出て、Form を表示できなくなりました。

    何がどうなり、どうしてこうなったのでしょう?

     

    サンプルを以下に置いておきます。

     

    - ダウンロード : サンプル

     

    また、エラーのコール スタックも以下に示します。
    各メソッドの引数は省略していますが、下記リンク先に全て残しています。

     

    - エラー時のコールスタック

     

    Code Snippet

    System.Data.SqlClient.SqlInternalConnection.OnError()
    System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
    System.Data.SqlClient.TdsParser.Run()
    System.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin()
    System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin()
    System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover()
    System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist()
    System.Data.SqlClient.SqlInternalConnectionTds..ctor()
    System.Data.SqlClient.SqlConnectionFactory.CreateConnection()
    System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection()
    System.Data.ProviderBase.DbConnectionPool.CreateObject()
    System.Data.ProviderBase.DbConnectionPool.UserCreateRequest()
    System.Data.ProviderBase.DbConnectionPool.GetConnection()
    System.Data.ProviderBase.DbConnectionFactory.GetConnection()
    System.Data.ProviderBase.DbConnectionClosed.OpenConnection()
    System.Data.SqlClient.SqlConnection.Open()
    System.Data.Common.DbDataAdapter.FillInternal()
    System.Data.Common.DbDataAdapter.Fill()
    System.Data.Common.DbDataAdapter.Fill()
    useUserControlWithMdf.syllabaryDataSetTableAdapters.columnsTableAdapter.Fill() .... (1)
    useUserControlWithMdf.UserControl1.UserControl1_Load()
    System.Windows.Forms.UserControl.OnLoad()
    System.Windows.Forms.UserControl.OnCreateControl()
    System.Windows.Forms.Control.CreateControl()
    System.Windows.Forms.Control.CreateControl()
    System.Windows.Forms.Control.ControlCollection.Add()
    System.Windows.Forms.Form.ControlCollection.Add()
    System.Windows.Forms.Design.ControlDesigner.DesignerControlCollection.Add()

     


    (1) の UserControl の Load() で呼んでいる Fill() で生じているようです。
    何が悪いのかなぁ? 同じプロジェクト内の mdf なのに。


    既に Form1 が呼び出している後に、また connection を開こうとして、
    「もうあるよ」といわれているのか?


    じゃあ、そんな場合、UserControl 上の DataGridView を Fill() するために、
    どう使えばいいのでしょう。

    2008年2月5日 18:50

回答

  • Fillしないといけないのはその通りだと思います。エラーの原因に関しては以下のページに説明があります。原文の英語の方がわかりやすいですね。

     

    Visual Studio 2005 でのローカル アタッチされたデータベース ファイルを使用するデータ連結オブジェクトがユーザー コントロールに保存されるならば、 Windows フォーム ベースのアプリケーションにユーザー コントロールを追加しようとすると、エラー メッセージを表示することがあります。
    http://support.microsoft.com/kb/908038/ja

    2008年2月6日 4:16
    モデレータ

すべての返信

  • Fillしないといけないのはその通りだと思います。エラーの原因に関しては以下のページに説明があります。原文の英語の方がわかりやすいですね。

     

    Visual Studio 2005 でのローカル アタッチされたデータベース ファイルを使用するデータ連結オブジェクトがユーザー コントロールに保存されるならば、 Windows フォーム ベースのアプリケーションにユーザー コントロールを追加しようとすると、エラー メッセージを表示することがあります。
    http://support.microsoft.com/kb/908038/ja

    2008年2月6日 4:16
    モデレータ
  •  trapemiya さんからの引用

    エラーの原因に関しては以下のページに説明があります。

    原文の英語の方がわかりやすいですね。

     

    またビンゴな回答、ありがとうございます。

     

    trapemiya さんの回答に助けられることが多いのですが、傾向がありますね、
    私の質問は。google で調べる前に、http://support.microsoft.com/kb/ を検
    索してみるといいのかも。

     

    また、英語のメッセージの方が検索キーワードが見つけやすい上に、

    英語圏の沢山の情報が得られやすいかもしれないと思いました。

    Express の英語版も入れた方がいいかもしれません。

     


    日本語、分かりづらいですねぇ。新たな混乱を生みました。

    今、指示されている方法を試しています。

     

    提示案の中で出てる "DesignTime" って何でしょう?

    使ったことない....

     

    2008年2月6日 5:41
  • - Visual Studio 2005 でのローカル アタッチされたデータベース ファイルを使用する ....

     

    1. Put code in a method instead of in the Form_Load section of the application. Then, you can call the method when you have to.
    2. Do not fill control data at design time. Instead, use the DesignTime property.


    UserControl1

    Code Snippet

    public partial class UserControl1 : UserControl
    {
      public UserControl1()
      {
        InitializeComponent();
      }

     

      public void fill()
      {
        this.columnsTableAdapter.Fill(this.syllabaryDataSet.columns);
      }
    }

     

    Form1

    Code Snippet

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

     

      private void Form1_Load(object sender, EventArgs e)
      {
        this.userControl1.fill();
      }
    }

     

     

    これで、先のエラーメッセージは出なくなりました。
    (1) で提案されている通りのことをしてないと思うのですが、間違ってないですかねぇ?


    (2) は "DesignTime" プロパティーというのが分からず。

    2008年2月6日 6:12
  •  custar さんからの引用

    (1) で提案されている通りのことをしてないと思うのですが、間違ってないですかねぇ?


    間違っていません。デザイン時にFillされなくなりますので。

     

     custar さんからの引用

    (2) は "DesignTime" プロパティーというのが分からず。

    今回のエラーの原因は以下の通りです。

    ユーザーコントロールをデザイン時にフォームに貼り付けた時点でLoadイベントが発生し、Fillしようとします。しかし、DataDirectoryが解決できず、デフォルトの場所である"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\"にあるsyllabary.mdfを探しに行き、それが存在しないためにエラーが発生しています。


    したがって、デザイン時かどうかを判断し、デザイン時であればFillしないようにLoadイベントに書けということだと思います。デザイン時かどうかはDesignModeプロパティで判断できます。

    2008年2月7日 15:33
    モデレータ
  •  trapemiya さんからの引用

    間違っていません。デザイン時に Fill されなくなりますので。

     

    コメントありがとうございます。


     trapemiya さんからの引用

    今回のエラーの原因は以下の通りです。

     

    ユーザーコントロールをデザイン時にフォームに貼り付けた時点で Load イベ
    ントが発生し、Fill しようとします。しかし、DataDirectory が解決できず、
    デフォルトの場所である "C:\Program Files\Microsoft Visual Studio
    9.0\Common7\IDE\" にある syllabary.mdf を探しに行き、それが存在しないた
    めにエラーが発生しています。

     

    へぇ、裏でそんな状態だったんですね。

     

    DataDirectory が解決できず、ってところが他のエラーのヒントになりそう。
    実は ClickOnce で SQL Server をインストールした後、自作アプリケーション
    が起動しようとしますが、TimeOut になって起動に失敗します。

     

    かなり再現性があります。別の機会に質問として挙げる予定です。


     trapemiya さんからの引用

    したがって、デザイン時かどうかを判断し、デザイン時であれば Fill しない
    ように Load イベントに書けということだと思います。デザイン時かどうかは
    DesignMode プロパティで判断できます。

     

    日本語の「デザイン時」とプロパティの "DesignTime" がかぶっていて、私の
    頭の中で混同してしまっているのですが、何かのオブジェクトのプロパティに
    "DesignTime" というのがあるんですか?

     

    もしかして、DesignTime ってデザイナで編集中の時のことでしょうか?

    でも、もしそうだとしても、何処でそんなプロパティを確認できるのだろう?

    見当たらない。

    2008年2月7日 17:04
  •  custar さんからの引用

    もしかして、DesignTime ってデザイナで編集中の時のことでしょうか?

    でも、もしそうだとしても、何処でそんなプロパティを確認できるのだろう?

    見当たらない。

     

    DesignTimeはデザイナで編集中のことでしょう。それを判断するプロパティがDesignModeです。

     

    Component.DesignMode プロパティ
    http://msdn2.microsoft.com/ja-jp/library/system.componentmodel.component.designmode(VS.80).aspx

    2008年2月8日 0:38
    モデレータ
  •  trapemiya さんからの引用

    DesignTime はデザイナで編集中のことでしょう。
    それを判断するプロパティが DesignMode です。

     

    Component.DesignMode プロパティ
    http://msdn2.microsoft.com/ja-jp/library/system.componentmodel.component.designmode(VS.80).aspx


    Design"Time" じゃなくて Design"Mode" なんですね。

     

    Design???? を見た瞬間、Design"Time" と思い込んで調べていました。
    # msdn にすら無い情報をどうやって使ってるんだ?と不思議でした。

     

    Form.cs 内で this.DesignMode としてプロパティを確認しました。

     

    再三の情報、ありがとうございました。

    2008年2月8日 3:09