none
SQL Server Compact Edition 3.5 で、接続を閉じるときにフリーズすることがある RRS feed

  • 質問

  • いつも助けていただき、ありがとうございます。

    SQL Server Compact Edition で接続を閉じる際に、フリーズするので困っています。
    現在は、特定の部位のみで起こっており、WindowsForm から呼び出した WPFコントロールが参照しているデータアクセスアセンブリー内でフリーズしています。
    呼び出し履歴を貼りつけると、以下のようになります。

         WindowsBase.dll!MS.Win32.UnsafeNativeMethods.WaitForMultipleObjectsEx(int nCount, System.IntPtr[] pHandles, bool bWaitAll, int dwMilliseconds, bool bAlertable) 行 301    C#
         WindowsBase.dll!System.Windows.Threading.DispatcherSynchronizationContext.Wait(System.IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) 行 77 + 0x2b バイト    C#
         mscorlib.dll!System.Threading.SynchronizationContext.InvokeWaitMethodHelper(System.Threading.SynchronizationContext syncContext, System.IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) 行 248 + 0xf バイト    C#
         [ネイティブからマネージの移行]   
         [マネージからネイティブへの移行]   
         System.Data.SqlServerCe.dll!System.Data.SqlServerCe.SqlCeConnection.ObjectLifeTimeTracker.Close(bool isDisposing) + 0x3f1 バイト   
         System.Data.SqlServerCe.dll!System.Data.SqlServerCe.SqlCeConnection.Dispose(bool disposing) + 0xb2 バイト   
    >    System.dll!System.ComponentModel.Component.Dispose() 行 120    C#
         BasicLibrary.dll!Mind.SqlCeDBProvider.GetString(string SQL文 = "SELECT Col1 FROM Table1 where Col2='ABC' and Col3='DEF'") 行 37 + 0x57 バイト    C#

    Waitという文字列をもつメソッドが動いているのが分かります。なので、フリーズしているものと思われます。
    WindowsBase.dll なので、WPFを何とかすれば、よいのでしょうか?

    フリーズしている場所のコードは、特別なことをしているわけではありません。以下のコードのreturn のところで発生しているように、IDEでは見えます。
    たぶん、Dispose()が呼ばれているので、正確には、Using を抜けるときだと思われます。

            public string GetString(string SQL文)
            {
                using (var 接続 = new SqlCeConnection(接続文字列))
                {
                    var cmd = new SqlCeCommand(SQL文, 接続);
                    接続.Open();
                    var a=cmd.ExecuteScalar();
                    return (a==null)?null:a.ToString();
                }
            }

    「sql ce hang close」などでWEB検索すると、該当するページがありますが、解決には至りません。解決方法は、あるのでしょうか?
    2009年5月22日 6:07

すべての返信

  • フリーズとはどういう現象でしょうか? マウスカーソルを含めて画面表示が動かずキーボードも反応しない、とか?
    >    System.dll!System.ComponentModel.Component.Dispose() 行 120    C#
    この行が気になりました。GetString()で問題が発生しているのならこの行は入らないかと思いますが、貼り付けミスでしょうか?
    逆にSqlCeConnection.Dispose()(引数なし)がスタックトレースに含まれていないのも気になります。
    実は使っているのが3.5(2008)ではなく2005だったり…?

    質問とは別に"SELECT Col1 FROM Table1 where Col2='ABC' and Col3='DEF'"こういうパラメータを直接書くのはSQLインジェクションが気になります。
    2009年5月23日 2:17
  • フリーズとはどういう現象でしょうか? マウスカーソルを含めて画面表示が動かずキーボードも反応しない、とか?

    アプリケーションが全く反応しないハング状態です。OSに異常が生じるわけではありません。ウィンドウは、真っ黒で描画が行われない状態、そして、VS2008の一時停止で止めると、using ブロックを抜ける return のところで緑矢印で止まります。呼び出し履歴は、そのときのものです。

    >    System.dll!System.ComponentModel.Component.Dispose() 行 120    C#
    この行が気になりました。GetString()で問題が発生しているのならこの行は入らないかと思いますが、貼り付けミスでしょうか?
    逆にSqlCeConnection.Dispose()(引数なし)がスタックトレースに含まれていないのも気になります。

    貼りつけミスではありません。System.dll!System.ComponentModel.Component.Dispose()は、using を抜けるときのものでしょうか。.Net Framework の内部的な呼び出しなので、いずれにしても、マイコードでの直接の呼び出しによるものではありません。マイコードについては、GetString メソッドを張り付けました。

    実は使っているのが3.5(2008)ではなく2005だったり…?

    Synchronization Services でも使用していますので、それはありません。

    質問とは別に"SELECT Col1 FROM Table1 where Col2='ABC' and Col3='DEF'"こういうパラメータを直接書くのはSQLインジェクションが気になります。

    内部的な生成であり、ユーザーはこのSQLに少しも介入する余地がありません。SQL CEは、一度に一文しか発行できないため、更新や削除などのインジェクションはできないはずです。また、仮にできたとしても、単なる下り一方向のローカルのDBキャッシュなので、全く問題ありません。すぐに同期化され、内容は元に戻されるでしょう。

    2009年5月25日 1:18
  • アプリケーションが全く反応しないハング状態です。OSに異常が生じるわけではありません。
    こんな感じで具体的に書いてもらえないとこちらには伝わりませんよ。

    貼りつけミスではありません。System.dll!System.ComponentModel.Component.Dispose()は、using を抜けるときのものでしょうか。.Net Framework の内部的な呼び出しなので、いずれにしても、マイコードでの直接の呼び出しによるものではありません。

    Synchronization Services でも使用していますので、それはありません。
    この指摘でバージョン確認してくれることを期待していました。ちょっと説明します。
    Ver 3.5のSqlCeConnectionクラスにはDispose()メソッドがあり、Component.Dispose()を呼ばないはずです。逆にVer 3.1(2005)にはDispose()メソッドがなく継承元のComponent.Dispose()が呼ばれるはずです。
    Synchronization Servicesは当然Ver 3.5をロードしているでしょうが、作成したアプリケーションはローカルコピーなどでVer 3.1をロードしていたりしませんか? typeof(SqlCeConnection).Assembly.FullNameなどで実行時にロードされている本当のバージョンを確認してみてください。
    # という回答を作るためにVer 3.5とVer 3.1のダウンロード&インストールして確認してるんだけどなぁ…

    内部的な生成であり、ユーザーはこのSQLに少しも介入する余地がありません。
    まぁ安全と言うなら安全なのでしょう。
    2009年5月25日 2:28
  • Synchronization Servicesは当然Ver 3.5をロードしているでしょうが、作成したアプリケーションはローカルコピーなどでVer 3.1をロードしていたりしませんか? typeof(SqlCeConnection).Assembly.FullNameなどで実行時にロードされている本当のバージョンを確認してみてください。
    複数のバージョンの混在もあり得るということですので、SqlCeConnectionのインスタンスを作成しているところでブレークポイントで止めて、書いてくださった方法で厳密名を出力してみました。

    "System.Data.SqlServerCe, Version=3.5.1.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"

    これで見ると、3.5.1.0 なので、3.5 だと思います。
    # という回答を作るためにVer 3.5とVer 3.1のダウンロード&インストールして確認してるんだけどなぁ…
    わざわざすみません。ありがとうございます。ローカルデータベースキャッシュ のVSサポートについては、不安定で、VSの再起動が必用になるなど、結構手を焼いております。(このスレッドでは詳しく書きませんが……)
    2009年6月1日 8:55