使用 DataAdapter.Fill(DataSet) 填充後,透過 DataTable.Rows[index][column] 存取:
Dim connStr As String = ConfigurationManager.ConnectionStrings("ConnStr").ConnectionString
Using conn As New OleDbConnection(connStr)
conn.Open()
Dim sql As String = "SELECT * FROM NewsClass ORDER BY ClassId DESC"
Dim da As New OleDbDataAdapter(sql, conn)
Dim ds As New DataSet()
da.Fill(ds, "NewsTable")
Dim dt As DataTable = ds.Tables("NewsTable")
' 取得第 i 列、第 1 欄 (0-based) 的值
Dim i As Integer = 2 ' 第三列
Dim cellValue As String = dt.Rows(i)(1).ToString() ' 欄位索引或名稱皆可
' 或使用欄位名稱:dt.Rows(i)("ClassName").ToString()
End Using
注意:Rows 索引為 0-based;欄位可用索引或名稱存取,建議用名稱提升可讀性。
Using conn As New OleDbConnection(connStr)
conn.Open()
Dim sql As String = "SELECT ClassID, ClassName FROM NewsClass ORDER BY ClassId DESC"
Dim da As New OleDbDataAdapter(sql, conn)
Dim ds As New DataSet()
da.Fill(ds, "NewsTable")
DropDownList1.DataSource = ds.Tables("NewsTable")
DropDownList1.DataTextField = "ClassName" ' 顯示文字
DropDownList1.DataValueField = "ClassID" ' 實際值
DropDownList1.DataBind()
End Using
' 假設 dr 為 DataRow,包含 ClassID 欄位
Dim targetValue As String = dr("ClassID").ToString().Trim()
Dim item As ListItem = DropDownList1.Items.FindByValue(targetValue)
If item IsNot Nothing Then
item.Selected = True
End If
補充:AppendDataBoundItems="true" 可在繫結前保留手動加入的項目 (如「請選擇」)。
場景:tblNews 僅存 ClassID,顯示時需查詢 NewsClass 取得 ClassName。
<asp:DataGrid ID="dgNews" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundColumn DataField="Title" HeaderText="標題" />
<asp:TemplateColumn HeaderText="類別">
<ItemTemplate>
<asp:Label ID="lblClass" runat="server"
Text='<%# GetClassName(CInt(DataBinder.Eval(Container.DataItem, "ClassID"))) %>' />
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
Protected Function GetClassName(ByVal classID As Integer) As String
Using conn As New OleDbConnection(connStr)
conn.Open()
Dim sql As String = "SELECT ClassName FROM NewsClass WHERE ClassID = ?"
Dim cmd As New OleDbCommand(sql, conn)
cmd.Parameters.AddWithValue("@ClassID", classID)
Dim result As Object = cmd.ExecuteScalar()
Return If(result IsNot Nothing, result.ToString(), "未知分類")
End Using
End Function
上述寫法每列資料都會呼叫 GetClassName 執行一次查詢,若 Grid 有 50 列即產生 50 次資料庫往返。**解決方案**:
SELECT n.*, c.ClassName
FROM News n
LEFT JOIN NewsClass c ON n.ClassID = c.ClassID
ORDER BY n.PublishDate DESC
直接 BoundColumn DataField="ClassName",零額外查詢。
Private Function GetClassDict() As Dictionary(Of Integer, String)
Dim dict As Dictionary(Of Integer, String) = CType(Cache("ClassDict"), Dictionary(Of Integer, String))
If dict Is Nothing Then
dict = New Dictionary(Of Integer, String)()
Using conn As New OleDbConnection(connStr)
conn.Open()
Dim cmd As New OleDbCommand("SELECT ClassID, ClassName FROM NewsClass", conn)
Using reader As OleDbDataReader = cmd.ExecuteReader()
While reader.Read()
dict(CInt(reader("ClassID"))) = reader("ClassName").ToString()
End While
End Using
End Using
Cache.Insert("ClassDict", dict, Nothing, DateTime.Now.AddHours(1), Cache.NoSlidingExpiration)
End If
Return dict
End Function
Protected Function GetClassName(ByVal classID As Integer) As String
Dim dict = GetClassDict()
Return If(dict.ContainsKey(classID), dict(classID), "未知分類")
End Function
首次載入建立字典快取,後續 O(1) 查找,極大降低資料庫負載。
掌握 DataTable 存取、DropDownList 繫結與 TemplateColumn 資料轉換三大基礎技巧,並理解 N+1 查詢陷阱及其解決方案 (JOIN 或快取字典),能讓 ASP.NET 資料庫應用開發更得心應手、效能更優異。