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

わんくま同盟

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

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

ツリー一括表示

ObjectDisposedExceptionの対策について /fragile (18/10/03(Wed) 22:33) #88838
Re[1]: ObjectDisposedExceptionの対策について /魔界の仮面弁士 (18/10/04(Thu) 00:45) #88840
Re[1]: ObjectDisposedException /PANG2 (18/10/04(Thu) 11:13) #88841
  └ Re[2]: ObjectDisposedException /fragile (18/10/04(Thu) 16:37) #88854


親記事 / ▼[ 88840 ] ▼[ 88841 ]
■88838 / 親階層)  ObjectDisposedExceptionの対策について
□投稿者/ fragile (1回)-(2018/10/03(Wed) 22:33:41)

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

vb.netでOdbcConnection及びOdbcCommandを使用して
SQLServer2016を操作するソフトを作成していたのですが、
テーブルのupdateを行うストアドプロシージャ実行時に以下のエラーが
稀に発生して失敗してしまい、対処方法分かれば教えていただきたい次第です。

環境は以下の通りとなります。
[PC]
Windows8.1(アクセス側)
SQL Server2012(DB側)

[開発言語]
vb 2012


2018-10-02 13:58:41,220 [5736] [ERROR] 20181002_135841_220 [Int32 intExecuteStoredProc(System.String, System.Data.ParameterDirection[], System.String[], System.Data.Odbc.OdbcType[], Int32[], System.Object[])] :System.ObjectDisposedException: セーフ ハンドルは閉じられています。
   場所 System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
   場所 System.Data.Odbc.OdbcHandle..ctor(SQL_HANDLE handleType, OdbcHandle parentHandle)
   場所 System.Data.Odbc.OdbcConnectionHandle..ctor(OdbcConnection connection, OdbcConnectionString constr, OdbcEnvironmentHandle environmentHandle)
   場所 System.Data.Odbc.OdbcConnectionOpen..ctor(OdbcConnection outerConnection, OdbcConnectionString connectionOptions)
   場所 System.Data.Odbc.OdbcConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
   場所 System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
   場所 System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   場所 System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   場所 System.Data.ProviderBase.DbConnectionInternal.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   場所 System.Data.Odbc.OdbcConnection.Open()
   場所 GUID_Ctrl.clsDBAccess.intExecuteStoredProc(String strProcName, ParameterDirection[] ParamDirection, String[] strParam, OdbcType[] typParamType, Int32[] intParamLen, Object[] objParamValue)
2018-10-02 13:58:41,236 [5736] [ERROR] 【Err-Date】
2018/10/02 13:58:41
【Err-Info】
System.Exception: System.ObjectDisposedException: セーフ ハンドルは閉じられています。
   場所 System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
   場所 System.Data.Odbc.OdbcHandle..ctor(SQL_HANDLE handleType, OdbcHandle parentHandle)
   場所 System.Data.Odbc.OdbcConnectionHandle..ctor(OdbcConnection connection, OdbcConnectionString constr, OdbcEnvironmentHandle environmentHandle)
   場所 System.Data.Odbc.OdbcConnectionOpen..ctor(OdbcConnection outerConnection, OdbcConnectionString connectionOptions)
   場所 System.Data.Odbc.OdbcConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
   場所 System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
   場所 System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   場所 System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   場所 System.Data.ProviderBase.DbConnectionInternal.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   場所 System.Data.Odbc.OdbcConnection.Open()
   場所 GUID_Ctrl.clsDBAccess.intExecuteStoredProc(String strProcName, ParameterDirection[] ParamDirection, String[] strParam, OdbcType[] typParamType, Int32[] intParamLen, Object[] objParamValue)
   場所 GUID_Ctrl.clsDBAccess.intExecuteStoredProc(String strProcName, ParameterDirection[] ParamDirection, String[] strParam, OdbcType[] typParamType, Int32[] intParamLen, Object[] objParamValue)
   場所 GUID_Ctrl.GpubDBModule.sp_SetTcRireki(Char BothTypeNo, Int32 BothNo, DateTime StartTime, String HistoryState)



よろしくお願いします。

[ □ Tree ] 返信 編集キー/

▲[ 88838 ] / 返信無し
■88840 / 1階層)  Re[1]: ObjectDisposedExceptionの対策について
□投稿者/ 魔界の仮面弁士 (1871回)-(2018/10/04(Thu) 00:45:15)
2018/10/04(Thu) 12:09:08 編集(投稿者)

No88838 (fragile さん) に返信
> テーブルのupdateを行うストアドプロシージャ実行時に以下のエラーが
> 稀に発生して失敗してしまい、対処方法分かれば教えていただきたい次第です。

このあたりとか。OdbcConnection が GC に回収されているものと推察します。

https://msdn.microsoft.com/ja-jp/library/fh21e17c.aspx
https://social.msdn.microsoft.com/Forums/ja-JP/a2f26072-c2c6-4e65-af40-87f7bb59d02a/12487125401247912505125401247312467124931246312471125191253112?forum=csharpgeneralja


上記の OracleConnection の事例のように、
OdbcConnection インスタンスの寿命管理を見直してみてください。
[ 親 88838 / □ Tree ] 返信 編集キー/

▲[ 88838 ] / ▼[ 88854 ]
■88841 / 1階層)  Re[1]: ObjectDisposedException
□投稿者/ PANG2 (235回)-(2018/10/04(Thu) 11:13:07)
2018/10/04(Thu) 13:55:44 編集(投稿者)

No88838 (fragile さん) に返信
> System.Exception: System.ObjectDisposedException: セーフ ハンドルは閉じられています。
> 場所 System.Data.Odbc.OdbcConnection.Open()
> 場所 GUID_Ctrl.clsDBAccess.intExecuteStoredProc(String strProcName, ParameterDirection[]

intExecuteStoredProc メソッド内で、 Dispose 済の OdbcConnection を Open しているとか。

using (var conn = new System.Data.OleDb.OleDbConnection("コネクション文字列")) {
conn.Open();
//ストアドを呼ぶ
}

のようにOleDbConnection を毎回 new するのであれば問題ありません。
[ 親 88838 / □ Tree ] 返信 編集キー/

▲[ 88841 ] / 返信無し
■88854 / 2階層)  Re[2]: ObjectDisposedException
□投稿者/ fragile (2回)-(2018/10/04(Thu) 16:37:43)
返信ありがとうございます。

> intExecuteStoredProc メソッド内で、 Dispose 済の OdbcConnection を Open しているとか。
>
> using (var conn = new System.Data.OleDb.OleDbConnection("コネクション文字列")) {
> conn.Open();
> //ストアドを呼ぶ
> }
>
> のようにOleDbConnection を毎回 new するのであれば問題ありません。

Disposeを行っているタイミングはFinallyで行っているため、
意図的にDisposeをしている箇所がFinallyまで無いことから、勝手にDisposeが
発生したのではという推測なのですが、Close、Disposeコード以外での
オブジェクトの破棄がなぜ起こったのか調査中です。
魔界の仮面弁士様が記載していただいたガベージコレクションに
ついてまず調べようと考えています。

また、intExecuteStoredProc メソッドについては下記の通りです。

Public Function intExecuteStoredProc(strProcName As String, ParamDirection() As ParameterDirection, strParam() As String, typParamType() As Odbc.OdbcType, intParamLen() As Integer, objParamValue() As Object) As Integer

Dim strCurrentMethod As String = "[" & System.Reflection.MethodBase.GetCurrentMethod.ToString & "] "
Dim intFor As Integer = 0
Dim mComm As New OdbcCommand 'コマンドオブジェクトalue
Dim mConn As New OdbcConnection 'コネクションオブジェクト
Dim strPrc As String = ""
Dim intResult As Integer = 0

Try
If System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable = False Then
OutputSystemLog("clsDBAccess.Connect" & "ネットワークアダプターが正常に機能していません。" & ControlChars.NewLine)
Exit Function

End If

mConn.ConnectionString = ConnectSetting.getInstanse().ConnectString
mConn.Open() 'MasterDB接続

mComm = mConn.CreateCommand()
mComm.CommandType = CommandType.StoredProcedure

If strParam IsNot Nothing Then
For intFor = 0 To strParam.Length - 1
If strParam(intFor) IsNot Nothing Then
Select Case typParamType(intFor)
Case OdbcType.Char, OdbcType.Text, OdbcType.VarChar
mComm.Parameters.Add("@" & strParam(intFor), typParamType(intFor), intParamLen(intFor)).Value = objParamValue(intFor)

Case OdbcType.DateTime
mComm.Parameters.Add("@" & strParam(intFor), typParamType(intFor)).Value = DateTime.Parse(CStr(objParamValue(intFor)))

Case OdbcType.Date
mComm.Parameters.Add("@" & strParam(intFor), typParamType(intFor)).Value = Date.Parse(CStr(objParamValue(intFor)))

Case Else
mComm.Parameters.Add("@" & strParam(intFor), typParamType(intFor)).Value = objParamValue(intFor)

End Select
mComm.Parameters(intFor).Direction = ParamDirection(intFor)
End If
Next
End If

strPrc &= "{call " & strProcName & " "

If strParam IsNot Nothing Then
If strParam(0) IsNot Nothing Then
For intFor = 0 To (strParam.Length - 1)
If intFor = 0 Then
strPrc &= "("
End If
strPrc &= "?"
If intFor <> (strParam.Length - 1) Then
strPrc &= ","
Else
strPrc &= ")"
End If
Next

Else
mComm.Parameters.Clear()
End If
End If
strPrc &= "}"

mComm.CommandText = strPrc

intResult = mComm.ExecuteNonQuery

Catch ex As Exception
OutputErrorLog(strCurrentMethod & ":" & ex.ToString)
Throw New Exception(ex.ToString)
Finally
mComm.Dispose()
mConn.Close() 'DB接続の解除
mConn.Dispose()
mConn = Nothing
End Try
Return (intResult)

End Function

[ 親 88838 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -