我知道我应该始终处置DataAdapter实例。在大多数情况下,我在关闭连接后立即处理它,但是在用户将修改DataTable项目(在ListBox或DataGridView中显示)的情况下,我创建DataAdapter,使用它来填充DataTable,但不要#39 ; t处理它直到用户点击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
他们习惯于调用填充DataTable的LoadDT
,因此我可以选择是否传递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
将返回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 :(得分:1)
更新:您是对的,如果private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
ViewModel = new ViewModel();
ViewModel.Text = "x:Bind does not work";
this.Bindings.Update();
}
传递的实例用于某个方法,您将无法从方法中获得初始化MySqlDataAdapter
ByRef
- 声明。这些变量是只读的。在C#中,您得到this有意义的编译器错误:
错误CS1657无法通过' daCompanies'作为ref或out参数 因为它是一个使用变量'
它已记录here:
编译器错误 CS1657
无法通过'参数'作为参考或出局的论据因为'原因'' 当变量作为ref或out参数传递时,会发生此错误 在该变量是只读的上下文中。只读上下文 包括foreach迭代变量,使用变量和修复 变量
在VB.NET中你可以这样做(所以编译器会忽略它,这几乎是一个bug)但是之后没有初始化变量。但如下所述,你不应该使用这种方法。
根据另一个问题:
如果您查看MSDN上的示例,您会发现微软也没有配置数据适配器。所以它没有必要。话虽如此,对于实现Using
的任何内容,使用Using
语句始终是最佳做法。
IDisposable
不是一个昂贵的对象,它不包含非托管资源(如连接)。因此,无论何时需要,都可以从中创建一个新实例。并且您不需要处理它,但这是一个可能在将来或DataAdapter
的不同实现中发生变化的实现细节,因此它仍然是处理它的最佳实践,最好使用DbDataAdapter
- 声明。
我不会使用您的方法,因为您将sql-string传递给方法,这通常会导致SQL注入漏洞。而是使用sql参数。
例如:
Using
不是传递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
,而是使用log4net等日志框架。