C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: VB.NETでADO使用時のロックについて


(過去ログ 139 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■81734 / inTopicNo.1)  VB.NETでADO使用時のロックについて
  
□投稿者/ となかい (1回)-(2016/11/04(Fri) 17:24:04)

分類:[VB.NET/VB2005 以降] 

2016/11/04(Fri) 17:25:16 編集(投稿者)
2016/11/04(Fri) 17:25:13 編集(投稿者)

VB.NETでADOを使って、MDBデータベースファイルに接続しているのですが、

Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim ca As ADOX.Catalog

cn = New ADODB.Connection()
cat= New ADOX.Catalog

cn.ConnectionString = 接続文字列
cn.Open()
cat.ActiveConnection = cn

こんな感じでカタログを用意した後、

Dim test as String = cat.Tables(0).Properties("Jet OLEDB:Link Datasource").Value

このようにテーブルの中の「Jet OLEDB:Link Datasource」の値を見ようとすると
接続しているDBが、その後Close()で閉じても実行ファイルが読み込んだDBを開いたままで
ロックしっぱなしの状態になってしまいます。(.ldbファイルが残って消せない)
実行ファイルを落とすとldbが消え、ロックが外れるのですが、
Close()でロックを解除するにはどうすればよいのでしょうか。

引用返信 編集キー/
■81737 / inTopicNo.2)  Re[1]: VB.NETでADO使用時のロックについて
□投稿者/ かたぎり (4回)-(2016/11/05(Sat) 11:47:21)
なつかしー、旧ADODB系とか、ADOXとか。

は、おいといて。
件のADOXなんですが、このクラスはCOMオブジェクト、と呼ばれるものに分類されてたと記憶してます。
つまり、きちんとDim句で変数を割りあてて、そのあと責任をもって、その変数をNothingする必要があるんです。

なので、
Dimした後で、Newする前にTry-catchでくるんで、Finallyで確実にDimした変数をNothingしてみてください。
こうすることで、プロセスがそのCOMへのアクセスを終了しました、とOSに通知できるのでOSからAccessにldb外していいよ、と通知するはず。

プロセスが終了するとldbが外れるのは、それが理由だと思います。

ためしてみてやってください。


No81734 (となかい さん) に返信
> 2016/11/04(Fri) 17:25:16 編集(投稿者)
> 2016/11/04(Fri) 17:25:13 編集(投稿者)
>
> VB.NETでADOを使って、MDBデータベースファイルに接続しているのですが、
>
> Dim cn As ADODB.Connection
> Dim rs As ADODB.Recordset
> Dim ca As ADOX.Catalog
>
> cn = New ADODB.Connection()
> cat= New ADOX.Catalog
>
> cn.ConnectionString = 接続文字列
> cn.Open()
> cat.ActiveConnection = cn
>
> こんな感じでカタログを用意した後、
>
> Dim test as String = cat.Tables(0).Properties("Jet OLEDB:Link Datasource").Value
>
> このようにテーブルの中の「Jet OLEDB:Link Datasource」の値を見ようとすると
> 接続しているDBが、その後Close()で閉じても実行ファイルが読み込んだDBを開いたままで
> ロックしっぱなしの状態になってしまいます。(.ldbファイルが残って消せない)
> 実行ファイルを落とすとldbが消え、ロックが外れるのですが、
> Close()でロックを解除するにはどうすればよいのでしょうか。
>
引用返信 編集キー/
■81740 / inTopicNo.3)  Re[2]: VB.NETでADO使用時のロックについて
□投稿者/ となかい (2回)-(2016/11/05(Sat) 14:23:04)
レスありがとうございます!
すいません、簡潔に書こうといろいろ省きましたが、確実な DimのNothingは行っているのです。
昔はこんなことなかったのですが、ActiveX Data Objectのバージョンで何か仕様が変わったのかなと思いましたが;

不思議なことにProperties("Jet OLEDB:Link Datasource").Valueでこの値を見なければCloseできるのですが、(ロックも外れる)
この値を取得したとたんCloseが効かなくなるのです。

別の手段とかあればよいのですが・・


No81737 (かたぎり さん) に返信
> なつかしー、旧ADODB系とか、ADOXとか。
>
> は、おいといて。
> 件のADOXなんですが、このクラスはCOMオブジェクト、と呼ばれるものに分類されてたと記憶してます。
> つまり、きちんとDim句で変数を割りあてて、そのあと責任をもって、その変数をNothingする必要があるんです。
>
> なので、
> Dimした後で、Newする前にTry-catchでくるんで、Finallyで確実にDimした変数をNothingしてみてください。
> こうすることで、プロセスがそのCOMへのアクセスを終了しました、とOSに通知できるのでOSからAccessにldb外していいよ、と通知するはず。
>
> プロセスが終了するとldbが外れるのは、それが理由だと思います。
>
> ためしてみてやってください。
>
>
> ■No81734 (となかい さん) に返信
>>2016/11/04(Fri) 17:25:16 編集(投稿者)
>>2016/11/04(Fri) 17:25:13 編集(投稿者)
>>
>>VB.NETでADOを使って、MDBデータベースファイルに接続しているのですが、
>>
>>Dim cn As ADODB.Connection
>>Dim rs As ADODB.Recordset
>>Dim ca As ADOX.Catalog
>>
>>cn = New ADODB.Connection()
>>cat= New ADOX.Catalog
>>
>>cn.ConnectionString = 接続文字列
>>cn.Open()
>>cat.ActiveConnection = cn
>>
>>こんな感じでカタログを用意した後、
>>
>>Dim test as String = cat.Tables(0).Properties("Jet OLEDB:Link Datasource").Value
>>
>>このようにテーブルの中の「Jet OLEDB:Link Datasource」の値を見ようとすると
>>接続しているDBが、その後Close()で閉じても実行ファイルが読み込んだDBを開いたままで
>>ロックしっぱなしの状態になってしまいます。(.ldbファイルが残って消せない)
>>実行ファイルを落とすとldbが消え、ロックが外れるのですが、
>>Close()でロックを解除するにはどうすればよいのでしょうか。
>>
引用返信 編集キー/
■81742 / inTopicNo.4)  Re[3]: VB.NETでADO使用時のロックについて
□投稿者/ かたぎり (5回)-(2016/11/05(Sat) 19:10:51)
2016/11/05(Sat) 19:13:29 編集(投稿者)
2016/11/05(Sat) 19:13:19 編集(投稿者)
言葉足らずでした、すみません

まず、dimする変数について、から突っ込んで話すと
cn,rs,catはもちろんNothingするんですけど
cat.tables(0)もDIMした変数にとって、nothingします。
あと、コード内のtestもDimしてNothing、宣言と同時に値割り当てはしないです。
げんみつにするなら、Properties("Jet OLEDB:Link Datasource")もDimした変数にとったほうがよいです。

COMを介してアクセスした(できた)ポインタ全部を離せない限り、使用中と判断されて外れないです。
そして離すときも、最初に宣言したものを最後に、
つまりスタックしてポップするイメージの順番でNothingしていきます。

COMはさむとメンドイんですよねorz
うまくいくときはさくっとうまくいくのですが、つかまれちゃうと関係した変数全部Nothingの勢いで
つぶしていかなくてはならない、というのが私の経験上のお話です。

No81740 (となかい さん) に返信
> レスありがとうございます!
> すいません、簡潔に書こうといろいろ省きましたが、確実な DimのNothingは行っているのです。
> 昔はこんなことなかったのですが、ActiveX Data Objectのバージョンで何か仕様が変わったのかなと思いましたが;
>
> 不思議なことにProperties("Jet OLEDB:Link Datasource").Valueでこの値を見なければCloseできるのですが、(ロックも外れる)
> この値を取得したとたんCloseが効かなくなるのです。
>
> 別の手段とかあればよいのですが・・
>
>
> ■No81737 (かたぎり さん) に返信
>>なつかしー、旧ADODB系とか、ADOXとか。
>>
>>は、おいといて。
>>件のADOXなんですが、このクラスはCOMオブジェクト、と呼ばれるものに分類されてたと記憶してます。
>>つまり、きちんとDim句で変数を割りあてて、そのあと責任をもって、その変数をNothingする必要があるんです。
>>
>>なので、
>>Dimした後で、Newする前にTry-catchでくるんで、Finallyで確実にDimした変数をNothingしてみてください。
>>こうすることで、プロセスがそのCOMへのアクセスを終了しました、とOSに通知できるのでOSからAccessにldb外していいよ、と通知するはず。
>>
>>プロセスが終了するとldbが外れるのは、それが理由だと思います。
>>
>>ためしてみてやってください。
>>
>>
>>■No81734 (となかい さん) に返信
> >>2016/11/04(Fri) 17:25:16 編集(投稿者)
> >>2016/11/04(Fri) 17:25:13 編集(投稿者)
> >>
> >>VB.NETでADOを使って、MDBデータベースファイルに接続しているのですが、
> >>
> >>Dim cn As ADODB.Connection
> >>Dim rs As ADODB.Recordset
> >>Dim ca As ADOX.Catalog
> >>
> >>cn = New ADODB.Connection()
> >>cat= New ADOX.Catalog
> >>
> >>cn.ConnectionString = 接続文字列
> >>cn.Open()
> >>cat.ActiveConnection = cn
> >>
> >>こんな感じでカタログを用意した後、
> >>
> >>Dim test as String = cat.Tables(0).Properties("Jet OLEDB:Link Datasource").Value
> >>
> >>このようにテーブルの中の「Jet OLEDB:Link Datasource」の値を見ようとすると
> >>接続しているDBが、その後Close()で閉じても実行ファイルが読み込んだDBを開いたままで
> >>ロックしっぱなしの状態になってしまいます。(.ldbファイルが残って消せない)
> >>実行ファイルを落とすとldbが消え、ロックが外れるのですが、
> >>Close()でロックを解除するにはどうすればよいのでしょうか。
> >>
引用返信 編集キー/
■81743 / inTopicNo.5)  Re[4]: VB.NETでADO使用時のロックについて
□投稿者/ となかい (3回)-(2016/11/05(Sat) 20:51:33)
レスありがとうございます!

う〜ん、処理を細かく Dim → 取得 → nothing と順番もしっかりして分割しても
Jet OLEDB:Link DatasourceのValueを取得した時点でCloseできなくなります。
VB.NETでのComの扱いがこうも複雑になっているとは思いませんでした。

調べていくと
System.Runtime.InteropServices.Marshal.FinalReleaseComObject などのメソッドも存在するとのことで
これも試してみましたがやっぱり離してくれないです;

DBの構造からダメな気がするのでADOやめておとなしくADO.NETで設計から作り直そうと思います(笑)
質問の解決にはなっていませんが、とりあえず解決にします。
お付き合いくださり、本当にありがとうございました。
解決済み
引用返信 編集キー/
■81744 / inTopicNo.6)  Re[1]: VB.NETでADO使用時のロックについて
□投稿者/ 魔界の仮面弁士 (938回)-(2016/11/05(Sat) 21:03:47)
No81734 (となかい さん) に返信
> Dim ca As ADOX.Catalog
> cat= New ADOX.Catalog
ca と cat を何か使い分けていますか?

処理イメージ。
テスト環境が無いので、実際に解放されるかは分かりません。


Dim cn As New ADODB.Connection()
Dim cat As New ADOX.Catalog
cn.ConnectionString = 接続文字列
cn.Open()
cat.ActiveConnection = cn

Dim tbls = cat.Tables
Dim tbl = tbls(0)
Dim props = tbl.Properties
Dim prop = props("Jet OLEDB:Link Datasource")
Dim test As String = CStr(prop.Value)
cat.ActiveConnection = Nothing
cn.Close()

If Marshal.IsComObject(prop) Then Marshal.ReleaseComObject(prop)
If Marshal.IsComObject(props) Then Marshal.ReleaseComObject(props)
If Marshal.IsComObject(tbl) Then Marshal.ReleaseComObject(tbl)
If Marshal.IsComObject(tbls) Then Marshal.ReleaseComObject(tbls)
If Marshal.IsComObject(cat) Then Marshal.ReleaseComObject(cat)
If Marshal.IsComObject(cn) Then Marshal.ReleaseComObject(cn)
引用返信 編集キー/
■81745 / inTopicNo.7)  Re[2]: VB.NETでADO使用時のロックについて
□投稿者/ なちゃ (147回)-(2016/11/06(Sun) 12:15:27)
誤解する人がいるとあれなので念のため補足しておきますが、.NETの世界ではNothingの代入は意味がありません。
※後でフラグ的な使い方を自分でする場合は別として

COMの場合に必要なのはMarshal.ReleaseComObjectの方です。

引用返信 編集キー/
■81746 / inTopicNo.8)  Re[3]: VB.NETでADO使用時のロックについて
□投稿者/ となかい (4回)-(2016/11/06(Sun) 14:02:45)
魔界の仮面弁士 様
サンプルまで提供して頂き誠にありがとうございます。
ここまでDimを分割しては試してませんでした。
かたぎり 様のおっしゃっていたのもこういうことだったのかと把握しました。
試してみたところ、正しく解放されました。
私の理解不足で本当にすいませんでした。
そして、本当にありがとうございました!


なちゃ 様
Nothingの代入の件、なるほどです。
とても勉強になりました。ありがとうございました!

皆様本当にありがとうございました!
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -