我对数据库值以及如何确定用户在某个时刻更改过的值的ID有疑问。
当前设置时,会有一个从数据集中填充的组合框,以及后续文本框,其文本应由从该组合框中选择的值确定。
因此,举个例子,您可以选择公司A'从组合框中,我希望数据集中该公司行的所有相应信息填充文本框(名称=公司A,地址= 123 ABC St.等)
我能够很好地填充组合框。但是,当我更改组合框的索引时,才会发生此特定错误:
未处理的类型' System.Data.OleDb.OleDbException' 发生在System.Data.dll
中其他信息:标准表达式中的数据类型不匹配。
以下是相应的代码:
Imports System.Data.OleDb
Public Class CustomerContact
Dim cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|datadirectory|\CentralDatabase.accdb;")
Dim da As New OleDbDataAdapter()
Dim dt As New DataTable()
Private Sub CustomerContact_Load(sender As Object, e As EventArgs) Handles MyBase.Load
cn.Open()
da.SelectCommand = New OleDbCommand("select * from Customers", cn)
da.Fill(dt)
Dim r As DataRow
For Each r In dt.Rows
cboVendorName.Items.Add(r("Name").ToString)
cboVendorName.ValueMember = "ID"
Next
cn.Close()
End Sub
Private Sub cboVendorName_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboVendorName.SelectedIndexChanged
cn.Open()
da.SelectCommand = New OleDbCommand("select * from Customers WHERE id='" & cboVendorName.SelectedValue & "'", cn)
da.Fill(dt)
Dim r As DataRow
For Each r In dt.Rows
txtNewName.Text = "Name"
txtAddress.Text = "Address"
Next
cn.Close()
End Sub
错误发生在第二行da.Fill(dt)的第24行。现在很明显,从异常中我知道我将错误的数据类型发送到OleDbCommand,不幸的是,当涉及到诸如此类的SQL命令时,我是一个新手。另外请记住,我甚至无法测试第二个For循环,它应该将客户信息填充到文本框中(为方便起见,我只复制了前两个文本框,其中总共有九个文本框) 。我认为我可以使用If语句来确定是否已经读取了行,并从那里填充了文本框,但是当我能够访问它时我会跳过这个障碍。
非常感谢任何指导或建议。我再次成为管理数据库的新手,所涉及的代码与项目有关,我目前的实习是让我为他们写的。
答案 0 :(得分:1)
由于您已经在DataTable
中拥有该表中的所有数据,因此根本不需要运行查询。表单加载设置(如果必须):
' form level object:
Private ignore As Boolean
Private dtCust As New DataTable
...
Dim SQL As String = "SELECT Id, Name, Address, City FROM Customer"
Using dbcon = GetACEConnection()
Using cmd As New OleDbCommand(SQL, dbcon)
dbcon.Open()
dtCust.Load(cmd.ExecuteReader)
End Using
End Using
' pk required for Rows.Find
ignore = True
dtCust.PrimaryKey = New DataColumn() {dtCust.Columns(0)}
cboCust.DataSource = dtCust
cboCust.DisplayMember = "Name"
cboCust.ValueMember = "Id"
ignore = False
忽略标志将允许您忽略由于DataSource
被设置而触发的第一个更改。这将在Display和Value成员设置之前触发。
初步问题/变更:
GetACEConnection
方法不是在任何地方连接字符串,而是为我创建它们。代码is in this answer。DataAdapter
只是填表,我用了一个读者Using
语句也会创建和处置Command
对象。通常,如果对象具有Dispose
方法,请将其放在Using
块中。dr(1) = ...
- 除其他外)。重要的是,我不是将项目添加到cbo,而是使用DataTable
作为组合的DataSource
。没有ValueMember
,DataSource
不会做任何事情 - 这是您遇到的核心问题。没有DataSource
,因此SelectedValue
始终为Nothing
。
然后在SelectedValueChanged
事件:
Private Sub cboCust_SelectedValueChanged(sender As Object,
e As EventArgs) Handles cboCust.SelectedValueChanged
' ignore changes during form load:
If ignore Then Exit Sub
Dim custId = Convert.ToInt32(cboCust.SelectedValue)
Dim dr = dtCust.Rows.Find(custId)
Console.WriteLine(dr("Id"))
Console.WriteLine(dr("Name"))
Console.WriteLine(dr("Address"))
End Sub
使用所选值,我在DataTable
中找到相关行。查找返回DataRow
(或Nothing),以便我可以访问所有其他信息。结果:
4
戈蒂埃
sdfsdfsdf
另一种选择是:
Dim rows = dtCust.Select(String.Format("Id={0}", custId))
这将返回符合条件的DataRow
数组。当目标列是文本时,String.Format
很有用。此方法不需要上面的PK定义:
Dim rows = dtCust.Select(String.Format("Name='{0}'", searchText))
有关详细信息,请参阅:
GetACEConnection