DataAdapter 在到达 "End Using" 之前被释放
DataAdapter is disposed before reaching "End Using"
我知道我应该始终处理 DataAdapter 实例。在大多数情况下,我会在关闭连接后立即处理它,但在用户将修改 DataTable 项目(显示在 ListBox 或 DataGridView 中)的情况下,我会创建 DataAdapter,用它来填充 DataTable,但不要处理它直到用户点击 Save
调用 DataAdapter.Update(DataTable)
... 这不是我的主要问题,但这是正确的方法吗?
回到正题,我有这两个功能:
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
它们习惯于调用 LoadDT
来填充 DataTable,因此我可以选择是否传递 DataAdapter。
现在我对一些事情感到困惑:当使用第一个 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
将 return 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
Update:你是对的,如果 ByRef
传递的实例用于Using
语句。这些变量是只读的。在 C# 中,您会收到 this 有意义的编译器错误:
Error CS1657 Cannot pass 'daCompanies' as a ref or out argument
because it is a 'using variable'
已记录 here:
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.
在VB.NET中你可以这样做(所以编译器会忽略它,这几乎是一个错误)但是之后变量没有被初始化。但是如下所述,无论如何你都不应该使用这种方法。
根据另一个问题:
如果您查看 MSDN 上的示例,您会发现 Microsoft 也没有处理数据适配器。所以它真的没有必要。话虽如此,对实现 IDisposable
.
的任何内容使用 Using
语句始终是最佳实践
A DataAdapter
不是昂贵的对象,它不包含非托管资源(如连接)。因此,在任何需要的地方从中创建一个新实例并没有什么坏处。你不需要处理它,但这是一个实现细节,将来可能会发生变化,或者在 DbDataAdapter
的不同实现中发生变化,所以处理它仍然是最佳做法,最好使用 Using
-声明。
我不会使用您的方法,因为您将 sql 字符串传递给通常会导致 sql 注入漏洞的方法。而是使用 sql 参数。
例如:
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
我不会传递 errorText
ByRef
,而是使用像 log4net.
这样的日志记录框架
我知道我应该始终处理 DataAdapter 实例。在大多数情况下,我会在关闭连接后立即处理它,但在用户将修改 DataTable 项目(显示在 ListBox 或 DataGridView 中)的情况下,我会创建 DataAdapter,用它来填充 DataTable,但不要处理它直到用户点击 Save
调用 DataAdapter.Update(DataTable)
... 这不是我的主要问题,但这是正确的方法吗?
回到正题,我有这两个功能:
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
它们习惯于调用 LoadDT
来填充 DataTable,因此我可以选择是否传递 DataAdapter。
现在我对一些事情感到困惑:当使用第一个 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
将 return 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
Update:你是对的,如果 ByRef
传递的实例用于Using
语句。这些变量是只读的。在 C# 中,您会收到 this 有意义的编译器错误:
Error CS1657 Cannot pass 'daCompanies' as a ref or out argument because it is a 'using variable'
已记录 here:
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.
在VB.NET中你可以这样做(所以编译器会忽略它,这几乎是一个错误)但是之后变量没有被初始化。但是如下所述,无论如何你都不应该使用这种方法。
根据另一个问题:
如果您查看 MSDN 上的示例,您会发现 Microsoft 也没有处理数据适配器。所以它真的没有必要。话虽如此,对实现 IDisposable
.
Using
语句始终是最佳实践
A DataAdapter
不是昂贵的对象,它不包含非托管资源(如连接)。因此,在任何需要的地方从中创建一个新实例并没有什么坏处。你不需要处理它,但这是一个实现细节,将来可能会发生变化,或者在 DbDataAdapter
的不同实现中发生变化,所以处理它仍然是最佳做法,最好使用 Using
-声明。
我不会使用您的方法,因为您将 sql 字符串传递给通常会导致 sql 注入漏洞的方法。而是使用 sql 参数。
例如:
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
我不会传递 errorText
ByRef
,而是使用像 log4net.