[VB.NET] การโหลดและบันทึกข้อมูลแบบไม่ซ้ำกันระหว่าง ComboBox และระบบฐานข้อมูล MS Access
http://www.g2gnet.com/webboard/images/vbnet/FillSaveComboBox.pngจากโปรเจค แจกฟรีโค้ดโปรแกรมการเก็บบันทึกข้อมูลบุคคล โดยใช้ VB.NET + MS Access 2007+ เรามาดูในส่วนย่อยของการใช้ ComboBox ก็เพื่อเชื่อมความสัมพันธ์กันแบบ One to One ซึ่งโค้ดในบทความนี้จะเป็นต้นฉบับ ก่อนที่จะทำให้มันกลายไปเป็นโปรแกรมย่อย หรือฟังค์ชั่นเพื่อในงานจริง เพราะถ้าหากเราใช้ ComboBox เพียงตัวเดียวก็ไม่มีปัญหา แต่ทีนี้งานมันมีมากกว่า 1 ตัวนี่ซิ ... โดยตัวอย่างนี้จะใช้ตาราง tblPosition หรือแสดงตำแหน่งพนักงาน คำว่า One To One หมายความว่าพนักงาน 1 คน จะมีตำแหน่งได้เพียง 1 ตำแหน่งเท่านั้น (ในทางปฏิบัติจริงอาจจะมีมากกว่า 1 ตำแหน่งได้ แต่ตอนนี้เอาแบบพื้นฐานเบื้องต้นก่อนข่ะรับ) ...
ขออารัมภบทเล็กน้อย ในการออกแบบตารางข้อมูลตาม ทฤษฎีบทของทองก้อน (Thongkorn's Theorem) หากฟิลด์ข้อมูลใดมีค่าที่ซ้ำๆกันในตารางนั้น ให้แยกฟิลด์นั้นออกไปอยู่อีก 1 ตาราง จากนั้นจับมันกลับเข้ามาเชื่อมความสัมพันธ์กันใหม่อีกครั้ง จะปรากฏดังรูป
http://www.g2gnet.com/webboard/images/vbnet/FillSaveComboBoxDB.png
ที่เรียกว่า ความสัมพันธ์แบบ 1 ต่อ 1 ก็เพราะค่า PositionFK ในตารางหลัก tblContact จะมีความสัมพันธ์กับ PositionPK ในตารางย่อย tblPosition เพียงค่า 1 ค่า เช่น PositionFK และ PositionPK = 14 มันมีค่า PositionName = IT Specialist และค่าตำแหน่งนี้ก็จะมีอยู่ด้วยกัน 2 คน แต่ค่า "IT Specialist" มันจะเก็บค่าเอาไว้เพียง 1 ค่าเท่านั้นในตาราง tblPosition ... การแยกย่อยตารางออกไป ก็เพื่อลดความซ้ำซ้อนของข้อมูล และทำให้ลดขนาดของไฟล์ฐานข้อมูล (DataBase) ลงไปด้วยนั่นเอง ประเด็นที่สำคัญคือ มันเกิดความยืดหยุ่น อำนวยความสะดวกให้กับผู้ใช้งาน แต่ทั้งนี้ทั้งนั้นมันก็ต้องมาพร้อมกับการเขียนโปรแกรมที่ยากขึ้นไปอีกนั่นเอง ...
มาดูโค้ดในส่วนของการโหลดข้อมูลเข้าสู่ ComboBox
' / --------------------------------------------------------------------------------
' / Load Position data into ComboBox
Private Sub PopulateComboBox()
strSQL = "SELECT * FROM tblPosition ORDER BY PositionName "
'// Initialize ComboBox
With cmbPositionName
.DropDownStyle = ComboBoxStyle.DropDown
.AutoCompleteMode = AutoCompleteMode.Suggest
.AutoCompleteSource = AutoCompleteSource.ListItems
End With
'//
Try
If Conn.State = ConnectionState.Closed Then Conn.Open()
Cmd = New OleDb.OleDbCommand(strSQL, Conn)
Dim DR As OleDb.OleDbDataReader = Cmd.ExecuteReader
Dim DT As DataTable = New DataTable
DT.Load(DR)
'/ Primary Key = ValueMember
cmbPositionName.ValueMember = "PositionPK"
'/ Display with field PositionName
cmbPositionName.DisplayMember = "PositionName"
'// Bind data source to control.
cmbPositionName.DataSource = DT
DR.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
เมื่อเราทำการป้อนค่าเข้าไปยัง ComboBox จากนั้นทำการบันทึก (Save) จะต้องไป ตรวจสอบก่อนว่าค่าที่ป้อนเข้าไปใหม่มันมีอยู่แล้วหรือไม่
' / --------------------------------------------------------------------------------
' / Check duplicate data, If exist data then return <> 0
Function CheckDuplicateName() As Integer
' Blank, and used TRIM for cut the head and tail spaces.
If Trim(cmbPositionName.Text) = "" Then Return 1
strSQL = _
" SELECT Count(tblPosition.PositionName) AS CountName FROM tblPosition " & _
" WHERE PositionName = " & "'" & Trim(cmbPositionName.Text) & "'"
If Conn.State = ConnectionState.Closed Then Conn.Open()
Cmd = New OleDb.OleDbCommand(strSQL, Conn)
' Return count records
CheckDuplicateName = CInt(Cmd.ExecuteScalar)
End Functionหากมีค่าซ้ำมันจะรีเทิร์น หรือส่งค่ากลับมากกว่า 1 ก็ให้ข้ามไป หากมีค่าเป็น 0 แสดงว่าค่าที่ป้อนเข้าไปใหม่ยังไม่มี ก็ให้ทำการบันทึกเข้าสู่ตาราง
แต่ก่อนที่จะบันทึกข้อมูล จะต้องทำการหาค่า Primary Key ตัวใหม่ ซ่ะก่อน
' / --------------------------------------------------------------------------------
' / Populate Primary Key for new Position Name and Return Primary Key.
Function SetupNewPK() As Long
strSQL = " SELECT MAX(tblPosition.PositionPK) AS MaxPK FROM tblPosition "
If Conn.State = ConnectionState.Closed Then Conn.Open()
Cmd = New OleDb.OleDbCommand(strSQL, Conn)
'/ Check exist data and return value
If IsDBNull(Cmd.ExecuteScalar) Then
SetupNewPK = 1
Else
SetupNewPK = CLng(Cmd.ExecuteScalar) + 1
End If
End Function
ทำการบันทึกข้อมูลค่าตำแหน่ง (Position) ใหม่
' / --------------------------------------------------------------------------------
' / Save data from ComboBox into DataBase
Private Sub SaveData()
Try
' / Create New Primary Key for PositionName
Dim PK As Integer = SetupNewPK()
'/ ------------------------------------------------------------------
If Conn.State = ConnectionState.Closed Then Conn.Open()
'// Set your query to a variable(strSQL)
strSQL = "INSERT INTO tblPosition (PositionPK, PositionName) Values (" & PK & ", '" & Trim(cmbPositionName.Text) & "')"
Dim DA As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(strSQL, Conn)
'// Fill and add or refreshes rows in the dataset
Dim DS As New DataSet
DA.Fill(DS)
'// Refresh data in ComboBox
Dim strPos As String = Trim(cmbPositionName.Text)
'// Load Data into ComboBox
Call PopulateComboBox()
' Check value and show
cmbPositionName.Text = strPos
cmbPositionName.Focus()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End SubConclusion: นี่คือกระบวนการคิดแบบเป็นขั้นเป็นตอน โดยทำการแยกย่อยงานต่างๆออกมาให้ได้ก่อน จากนั้นทำการเขียนโค้ดและทดสอบว่ามันได้ผลอย่างที่ต้องการหรือไม่ แล้วค่อยตัดต่อไปใช้กับงานจริงต่อไป มันก็จะลดปัญหาเรื่องของข้อผิดพลาดที่เราเรียกกันว่า "Bug" ได้ครับทั่นผู้ชม ... สวัสดี
ดาวน์โหลดโค้ดต้นฉบับ VB.NET (2010) ได้ที่นี่
Code อาจารย์เป็น สากล เลยครับ ผมไปแจกโค้ดตามเว็บนอกด้วยครับ ก็เลยมีโอกาสได้รู้จัก และแลกเปลี่ยนความรู้ แนวคิดกับบรรดาโปรแกรมเมอร์ต่างชาติเขาไปพร้อมๆกันครับ ขอบคุณครับ ขอบคุณครับ
หน้า:
[1]