2016-07-08 9 views
1

DataAdapterインスタンスを常に破棄する必要があることはわかっています。ほとんどの場合、私は接続を閉じた直後に処理を中止しますが、ユーザーがDataTable項目(ListBoxまたはDataGridViewに表示されている)を変更するような場合には、DataAdapterを作成してDataTableを埋めるために使用しますが、ユーザーがSaveをクリックしてDataAdapter.Update(DataTable) ... を呼び出すまでは私の主な質問ではありませんが、これは正しいアプローチですか?"End Using"に達する前にDataAdapterが破棄される

Public Function LoadCompaniesDT(ByRef dtCompanies As DataTable) As Boolean 
    Using daCompanies As MySqlDataAdapter = Nothing 
     Return LoadCompaniesDT(daCompanies, dtCompanies) 
    End Using 
End Function 

Public Function LoadCompaniesDT(ByRef daCompanies As MySqlDataAdapter, ByRef dtCompanies As DataTable) As Boolean 
    Dim sql As String = "SELECT * FROM companies" 
    Return LoadDT(daCompanies, dtCompanies, sql, Res.CompaniesFailedMsgBody) 
End Function 

彼らは、私は選択肢がデータアダプターを渡したりしないように持っているので、DataTableを設定しLoadDTを呼び出すために使用している:

戻るメインの質問に、私はこれらの2つの機能を持ちます。最初LoadCompaniesDT機能を使用する場合、daCompaniesは次のように.. End Usingに達する前に配置されている:

Public Function LoadCompaniesDT(ByRef dtCompanies As DataTable) As Boolean 
    Using daCompanies As MySqlDataAdapter = Nothing 
     Dim tmp As Boolean = LoadCompaniesDT(daCompanies, dtCompanies) 
     Console.WriteLine(daCompanies Is Nothing) ' ==> True!! 
     Return tmp 
    End Using 
End Function 

注:

は今、私は何かについて困惑している私はDim daCompanies代わりUsing daCompaniesで使用した場合、その後daCompanies Is Nothingが返されますFalse。


LoadDT機能コード:

Private Function LoadDT(ByRef da As MySqlDataAdapter, ByRef dt As DataTable, 
                 ByVal sqlQuery As String, 
                 ByVal errorText As String) As Boolean 
    Dim connStr As String = String.Format("server={0}; port={1}; user id={2}; password={3}; database={4}", 
              DbServer, DbServerPort, DbUserName, DbPassword, DatabaseName) 
    Dim conn As MySqlConnection = New MySqlConnection(connStr) 
    Dim cmd As MySqlCommand = New MySqlCommand 

    Try 
     conn.Open() 

     cmd.CommandType = CommandType.Text 
     cmd.CommandText = sqlQuery 
     cmd.Connection = conn 

     da = New MySqlDataAdapter(cmd) 
     dt = New DataTable 
     da.Fill(dt) 

     Return True 
    Catch ex As Exception 
     MessageBox.Show(errorText, Res.ServerError, MessageBoxButtons.OK, MessageBoxIcon.Error) 
     Return False 
    Finally 
     cmd.Dispose() 
     cmd = Nothing 
     conn.Close() 
     conn.Dispose() 
    End Try 
End Function 
+0

これはこの問題の中核であるため、「ByRef」を含むようにタイトルを変更する必要があります。 –

答えて

1

更新:あなたは正しいByRef渡されたインスタンスがUsingで使用されている場合は、バックメソッドから初期化MySqlDataAdapterを得ることはありません - ステートメント。これらの変数は読み込み専用です。 (ほとんどですので、コンパイラはそれを無視するバグ)あなたがそれを行うことができますVB.NETで

Compiler Error CS1657

Cannot pass 'parameter' as a ref or out argument because 'reason'' This error occurs when a variable is passed as a ref or out argument in a context in which that variable is readonly. Readonly contexts include foreach iteration variables, using variables, and fixed variables.

が、変数:それはhereを文書化しています

Error CS1657 Cannot pass 'daCompanies' as a ref or out argument because it is a 'using variable'

:C#では、あなたはthis意味のコンパイラエラーを取得しますその後は初期化されません。しかし、以下に述べるように、あなたはこの方法をとにかく使用すべきではありません。


他の質問によると:あなたはMSDN上のサンプルを見れば

あなたは、Microsoftはまた、データアダプタを配置しないことがわかります。だから、それは本当に必要ではありません。しかし、Usingステートメントは、IDisposableを実装するもので使用することが常にベストプラクティスです。

DataAdapterは高価なオブジェクトではなく、アンマネージリソース(接続など)を保持しません。だからあなたが必要としているときに新しいインスタンスを作成することに傷つくことはありません。そして、それを処分する必要はありませんが、それは将来的に、または異なる実装のDbDataAdapterで変更される可能性のある実装の詳細です。したがって、Usingを使用すると、処分するのがベストプラクティスです。

SQLの文字列をメソッドに渡すため、SQLインジェクションが脆弱になることが多いため、私はあなたのアプローチを使用しません。代わりにSQLパラメータを使用します。例えば

:代わりに、私はlog4netのようなロギングフレームワークを使用したいerrorTextByRefを渡すの

Private Function LoadDT() As DataTable 
    Dim tbl As New DataTable() 
    'Load connection string from app.config or web.config 
    Dim sql As String = "SELECT * FROM companies" ' don't use * but list all columns explicitely 
    Using conn As New MySqlConnection(My.Settings.MySqlConnection) 
     Using da = New MySqlDataAdapter(sql, conn) 
      da.Fill(tbl) 
     End Using 
    End Using 
    Return tbl 
End Function 

+0

はい、これは[this](http://stackoverflow.com/q/18205560/4934172)の質問です。なぜ 'Using'ステートメントの終わりに達する前に処分されるのでしょうか? –

+0

@ GeniuSBraiN:私は私の答えを編集しました –

+0

私は参照してください。ありがとう、あなたの努力を助けてくれました:) –

関連する問題