MySql with C#, VB .NET

Programming Style ใน entry นี้ จะเป็นตอนพิเศษหน่อย คือจะเป็นการสอนการทำการโปรแกรมมิ่งผ่าน Database เบื้องต้น บน .NET Framework ซึ่ง เราจะทำงานบนองค์ประกอบที่ชื่อว่า OLEDB บน ADO.NET โดยจั้งใจเขียนเพื่อเพื่อนในสาขา ที่ไม่เคยได้เรียน VB หรือ C# มาก่อน
ทีนี้ เนื่องจากส่วนใหญ่องค์กร มักจะใช้ฐานข้อมูลที่ฟรี ฉะนั้น ในบทความนี้ เราจะยกตัวอย่างฐานข้อมูล MySQL เข้ามาใช้ในการอธิบาย เพื่อให้สามารถนำไปประยุกต์ใช้ได้โดยง่าย
สำหรับคนที่ต้องการหา MySQL มาลงในเครื่อง ถ้าอยากจะลงง่ายๆ แนะนำให้หา XAMPP มาลง เพราะเผื่ออนาคตต้องศึกษาพวก PHP หรืออะไรที่เกี่ยวกับเว็บ จะได้ใช้ XAMPP เป็นเซิฟเวอร์ในเครื่องได้เลย

ในขั้นตอนนี้ เราได้เซ็ตให้ฐานข้อมูลของเรา เพิ่ม user เข้าไป โดยมี ID: tan Password: mypassword และรันอยู่บน localhost (127.0.0.1) ซึ่ง ฐานข้อมูลที่เราจะนำมาใช้นั้น มีชื่อว่า student_score
ในที่นี้ ตัวฐานข้อมูลของเรา จะแบ่งออกเป็น 2 ส่วนด้วยกัน คือส่วนที่เก็บข้อมูลของนักศึกษา (Table:student) และข้อมูลของ วิชา (Table:subject) ซึ่งจะมีความสัมพันธ์กันแบบ Many to Many กล่าวคือ นักศึกษา 1 คน ลงทะเบียนได้หลายวิชา และ 1 วิชา ก็มีนักศึกษาหลายคน ซึ่งความสัมพันธ์แบบ Many-Many นี้ มันผิดหลักของ Database Design เนื่องจากไม่สามารถนำมาลงในฐานข้อมูลได้ เราจึงต้องสร้าง Junction Table ขึ้นมา เพื่อเชื่อมตรงกลาง โดยให้ primary ทั้ง 2 เป็น Composite Key นอกจากนี้ คะแนนในแต่ละวิชาของนักศึกษา ก็สามารถนำมาเก็บในตารางนี้ได้เช่นกัน
ซึ่งการสร้าง และ ป้อนข้อมูลลงในฐานข้อมูล จะไม่บอกในนี้ ให้ลองไปศึกษากันเอง
ขั้นตอนต่อไป คือการเริ่มต้นเขียนโปรแกรม
ก่อนอื่น เนื่องจากเราใช้ฐานข้อมูลของ MySQL ฉะนั้น ตัวของ .NET Framework จึงไม่มี Provider ที่สามารถเชื่อมต่อกับฐานข้อมูลได้โดยตรง เราจึงต้องไป Download ตัว Library เพื่อเชื่อมต่อกับฐานข้อมูล MySQL ที่ http://dev.mysql.com/downloads/connector/net/6.1.html ซึ่งวิธีการนำไปใช้นั้น เราสามารถศึกษาได้จาก http://www.codeproject.com/Articles/43438/Connect-C-to-MySQL หัวข้อ Using the Code >> Adding Reference and Creating the MySQL Connector DLL from the Project
ทีนี้ เราก็มาเริ่มเขี่ยโค้ดกัน
ก่อนอื่น เราต้องทำการเพิ่ม Namespace ของ MySQL เข้ามาซะก่อน ซึ่งให้เราใส่โค้ดนี้ ไปด้านบนสุดของโปรแกรม
[C#]
using MySql.Data.MySqlClient;
[VB]
Imports MySql.Data.MySqlClient
จากนั้น ลองสร้าง Form ขึ้นมา ดังนี้

จากนั้นให้เรากด F7 เพื่อเปลี่ยนไปในมุมมองแบบ Code ซึ่งภายใต้ Class Form1 ให้เราเพิ่ม MySqlConnection เข้าไป ซึ่งตัวของ MySqlConnection นี้ จะเป็นตัวที่คอยเชื่อมต่อกับฐานข้อมูลให้กับเรา
[C#]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
// use for connect to mysql server. Download at http://dev.mysql.com/downloads/connector/net/6.1.html
using MySql.Data.MySqlClient;
namespace DatabaseTutorialOLEDB
{
    public partial class Form1 : Form
    {
        private MySqlConnectionConnection = new MySqlConnection(“SERVER=localhost;DATABASE=student_score;UID=tan;PASSWORD=mypassword;”);
       
        public Form1()
        {
            InitializeComponent();
        }
    }
}
[VB]
Imports MySql.Data.MySqlClient
Public Class Form1
    Friend WithEventsConnection As NewMySqlConnection(“SERVER=localhost;DATABASE=student_score;UID=tan;PASSWORD=mypassword;”)
End Class
*สำหรับ VB สาเหตุที่ไม่ใช้ Dim เพราะว่า หากเราใช้ Dim เราจะไม่สามารถเพิ่ม Event ให้กับ Connection ทีหลังได้
ตรง SERVER=localhost นั้น เราสามารถเปลี่ยนไปใส่ IP หรือ URL ของ SERVER ได้
ทีนี้ ต่อไป เป็นฟังชั่นสำหรับเชื่อมต่อ หรือ ตัดการเชื่อมต่อฐานข้อมูล โดยเราจะทำผ่าน MySqlConnection ของเรา
[C#]
public bool Connect()
{
    try
    {
        Connection.Open();
        return true;
    }
    catch (MySqlExceptionex)
    {
        MessageBox.Show(ex.Message);
    }
    return false;
}
public bool Disconnect()
{
    try
    {
        Connection.Close();
        return true;
    }
    catch (MySqlExceptionex)
    {
        MessageBox.Show(ex.Message);
    }
    return false;
}
[VB]
    Public FunctionConnect() As Boolean
        Try
            Connection.Open()
            Return True
        Catch ex As MySqlException
            MessageBox.Show(ex.Message)
        End Try
        Return False
    End Function
    Public FunctionDisconnect() As Boolean
        Try
            Connection.Close()
            Return True
        Catch ex As MySqlException
            MessageBox.Show(ex.Message)
        End Try
        Return False
    End Function
ซึ่งต่อจากนี้ เราต้องการจะทำให้ปุ่ม conn_disconn_button ของเรา สามารถกดเพื่อทำการ เชื่อมต่อ/ตัดการเชื่อมต่อได้ ให้เราดับเบิ้ลคลิ๊กที่ปุ่ม ตัวโปรแกรมจะ Generate Event ขึ้นมา ให้เราทำการเพิ่มโค้ดเข้าไปดังนี้
[C#]
private voidconn_disconn_button_Click(object sender, EventArgs e)
{
    if (Connection.State == System.Data.ConnectionState.Closed)
    {
        Connect();
    }
    else if(Connection.State == System.Data.ConnectionState.Open)
    {
        Disconnect();
    }
}
[VB]
    Private Subconn_disconn_button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handlesconn_disconn_button.Click
        If Connection.State = System.Data.ConnectionState.Closed Then
            Connect()
        ElseIf Connection.State = System.Data.ConnectionState.Open Then
            Disconnect()
        End If
    End Sub
หรือพูดง่ายๆก็คือ ถ้าตอนนี้ MySqlConnection มีสถานะเป็น Close ก็ให้ทำการ Connect แต่ถ้าเป็น Open ก็ให้ทำการ Disconnect ซะ (โดยปกติ โปรแกรมประเภทนี้จะไม่เชื่อมต่อกับฐานข้อมูลตลอดเวลา เพราะมันเปลืองทรัพยากรระบบ แต่ที่เขียนแบบนี้เพื่อให้เข้าใจง่าย ถ้าใครไปทำโปรเจค ก็ให้แก้ตรงนี้ด้วย)
ทีนี้ หากเราต้องการให้มีการทำงานใดๆ หลังจากมีการเปลี่ยนแปลงสถานะก็ตาม เช่นเมื่อหลังจากเกิดการเชื่อมต่อ ให้แสดงข้อความว่า Connected แล้วเพิ่มข้อมูลลงไปในตาราง เราก็สามารถทำได้ผ่าน event MySqlConnection.StateChange หรือสามารถเพิ่มโค้ดเข้าไปได้ ดังนี้
[C#]
public Form1()
{
    InitializeComponent();
    // add event to Connection.StateChange
    Connection.StateChange += newSystem.Data.StateChangeEventHandler(Connection_StateChange);
}
//this function will called when MySqlConnection has state changed
void Connection_StateChange(objectsender, System.Data.StateChangeEventArgs e)
{
    if (e.CurrentState == System.Data.ConnectionState.Open)
    {
        ConnectStateLabel.Text = “Connected”;
        ConnectStateLabel.ForeColor = Color.Green;
        conn_disconn_button.Text = “Disconnect”;
        UpdateCombobox();
    }
    else if(e.CurrentState == System.Data.ConnectionState.Closed)
    {
        ConnectStateLabel.Text = “Disonnected”;
        ConnectStateLabel.ForeColor = Color.Red;
        conn_disconn_button.Text = “Connect”;
    }
    else if(e.CurrentState == System.Data.ConnectionState.Connecting)
    {
        ConnectStateLabel.Text = “Connecting”;
        ConnectStateLabel.ForeColor = Color.Blue;
    }
}
[VB]
    Private SubConnection_StateChange(ByVal sender As Object, ByVal e AsSystem.Data.StateChangeEventArgs) Handles Connection.StateChange
        If e.CurrentState = System.Data.ConnectionState.Open Then
            ConnectStateLabel.Text = “Connected”
            ConnectStateLabel.ForeColor = Color.Green
            conn_disconn_button.Text = “Disconnect”
            UpdateCombobox()
        ElseIf e.CurrentState = System.Data.ConnectionState.Closed Then
            ConnectStateLabel.Text = “Disonnected”
            ConnectStateLabel.ForeColor = Color.Red
            conn_disconn_button.Text = “Connect”
        ElseIf e.CurrentState = System.Data.ConnectionState.Connecting Then
            ConnectStateLabel.Text = “Connecting”
            ConnectStateLabel.ForeColor = Color.Blue
        End If
    End Sub
ซึ่งภายใน If-Condition ต่างๆนั้น เป็นการเพิ่มการแสดงสถานะการเชื่อมต่อเท่านั้น มีเพียง UpdateCombobox(); ที่เป็นฟังชั่น ที่จะคอยอัพเดท StudentID และ SubjectID ไปบน Combobox ต่างๆที่ต้องการ ซึ่งจะเริ่มมีการเรียกใช้การ Query กับฐานข้อมูลเบื้องต้น (แต่ยาก)
[C#]
private voidUpdateCombobox()
{
    MySqlCommand cmd = newMySqlCommand(“SELECT StudentID FROM student”, Connection);
    MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
    DataTable Table = newDataTable();
    adapter.Fill(Table);
    StudentIDCombobox.Items.Clear();
    foreach (var x in Table.Rows)
    {
        StudentIDCombobox.Items.Add(((DataRow)x)[0]);
    }
    cmd = new MySqlCommand(“SELECT SubjectID FROM subject”, Connection);
    adapter = new MySqlDataAdapter(cmd);
    Table = new DataTable();
    adapter.Fill(Table);
    SubjectIDCombobox.Items.Clear();
    foreach (var x in Table.Rows)
    {
        SubjectIDCombobox.Items.Add(((DataRow)x)[0]);
    }
}
[VB]
Private SubUpdateCombobox()
        Dim cmd As MySqlCommand = NewMySql.Data.MySqlClient.MySqlCommand(“SELECT StudentID FROM student”, Connection)
        Dim adapter As New MySqlDataAdapter(cmd)
        Dim Table As New DataTable()
        adapter.Fill(Table)
        StudentIDCombobox.Items.Clear()
        For Each x In Table.Rows
            StudentIDCombobox.Items.Add(DirectCast(x, DataRow)(0))
        Next
        cmd = New MySql.Data.MySqlClient.MySqlCommand(“SELECT SubjectID FROM subject”, Connection)
        adapter = New MySqlDataAdapter(cmd)
        Table = New DataTable()
        adapter.Fill(Table)
        SubjectIDCombobox.Items.Clear()
        For Each x In Table.Rows
            SubjectIDCombobox.Items.Add(DirectCast(x, DataRow)(0))
        Next
End Sub
เราควรจะค่อยๆดู Code แล้วค่อยๆทำความเข้าใจไปกับมันจะดีกว่า เนื่องจากในการ Query แต่ละครั้ง มักจะมีการทำงานที่คล้ายๆกัน แต่มี Class ที่ถูกเรียกใช้งานมาก เราจึงควรจะทำความเข้าใจให้ได้ เพราะมันจะยากมากๆ หากต้องจำขั้นตอนทั้งหมด
MySqlCommand
เป็นตัวที่คอยเก็บคำสั่ง SQL ต่างๆ เช่น INSERT, UPDATE, DELETE, SELECT หรือคำสั่งอื่นๆอีกมากมาย
MySqlDataAdapter
มีหน้าที่คอยรับค่าจาก Command ประเภทที่มีการรับค่ากลับ เช่น SELECT
DataTable
เป็นตัวที่คอยเก็บ Data ในรูปแบบของ Table เพื่อให้เราสามารถเข้าถึงข้อมูลในลักษณะของ Row, Column ได้ เป็น Class พื้นฐานใน System.Data
 
ขั้นตอนการทำงานของเราทุกครั้งคือ
1.       สร้าง MySqlCommandขึ้นมา โดยกำหนด Query และ Connection ให้เรียบร้อยเช่น 
[C#]
MySqlCommand cmd = new MySqlCommand(“SELECT StudentID FROM student”, Connection);
[VB]
Dim cmd As MySqlCommand= New MySql.Data.MySqlClient.MySqlCommand(“SELECT StudentID FROM student”, Connection)
2.       สร้าง MySqlDataAdapter ขึ้นมา เพื่อคอยอ่านข้อมูล โดยกำหนด Command ให้เรียบร้อย  
[C#]
MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
[VB]
Dim adapter As New MySqlDataAdapter(cmd)
3.       สร้าง DataTableไว้สำหรับนำข้อมูลเก็บลงตาราง จากนั้นให้ทำการป้อนข้อมูลจากMySqlDataAdapterลงไปในตารางโดย 
[C#]
DataTable Table = new DataTable();
adapter.Fill(Table);

[VB]
Dim Table As New DataTable()
adapter.Fill(Table)

 
หลังจากนั้น เราก็ต้องเคลีย ข้อมูลเดิมใน StudentIDCombobox ก่อน ก่อนจะใส่ข้อมูลใหม่ลงไป
StudentIDCombobox.Items.Clear();
หลังจากนั้น ก็ใส่ข้อมูลลงไปเลย
[C#]
foreach (var x in Table.Rows)
{
    StudentIDCombobox.Items.Add(((DataRow)x)[0]);
}
[VB]
        For Each x In Table.Rows
            StudentIDCombobox.Items.Add(DirectCast(x, DataRow)(0))
        Next
ข้างบนนี้ พยายามอ่านมันหน่อยนะ มันจะแปลเป็นภาษาคนว่า “สำหรับทุกๆ Row ใน Table ให้เพิ่มข้อมูลใน Colume แรก ของแต่ละ Row ลงไปใน StudentIDCombobox.Items
หลังจากนี้ ทุกครั้งที่เราทำการ Connect เสร็จ ตัวของ StudentIDCombobox และ SubjectIDComboboxก็จะทำการเพิ่มข้อมูล ให้เปลี่ยนไปตามที่เราเลือกได้
 
 
ต่อจากนี้ สิ่งที่เราต้องทำต่อไป คือการแสดงข้อมูลแบบเป็นตาราง ผ่าน DataGridView ในทุกครั้งที่มีการเปลี่ยน Selected_Index บน ComboBox
ในการเพิ่ม Event ให้เราทำการ ดับเบิ้ลคลิ๊กที่ StudentIDCombobox ตัวโปรแกรมจะ Generate Event ออกมาให้
private void StudentIDCombobox_SelectedIndexChanged(object sender, EventArgse)
{
   
}
ขั้นตอนต่างๆก็แทบจะเหมือนเดิม เพียงแค่เปลี่ยนจากเอา Column แรกมาใส่ เป็น ใส่ลงไปทั้งตาราง ลงไปใน dataGridView1แต่สิ่งที่จะยาก คือตัว Query Command เอง เพราะต้องมีการดึงข้อมูลจากหลายตาราง ซึ่งอาจทำให้งงได้ หากใครลืมไปแล้ว (ใครจำโครงสร้างตารางไม่ได้ ขึ้นไปดูรูปข้างบน)
ตัวอย่างของโค้ด (เว้นตรง (“Query Command string here”ไว้)
private void StudentIDCombobox_SelectedIndexChanged(object sender, EventArgse)
{
    MySqlCommand cmd = newMySql.Data.MySqlClient.MySqlCommand(/*Query Command string here*/, Connection);
    MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
    DataTable Table = newDataTable();
    adapter.Fill(Table);
    dataGridView1.DataSource = Table;
}
    Private SubStudentIDCombobox_SelectedIndexChanged(ByValsender As Object, ByVal e As EventArgs) HandlesStudentIDCombobox.SelectedIndexChanged
        Dim cmd As MySqlCommand = NewMySql.Data.MySqlClient.MySqlCommand(“Query Command string here”, Connection)
        Dim adapter As New MySqlDataAdapter(cmd)
        Dim Table As New DataTable()
        adapter.Fill(Table)
        dataGridView1.DataSource = Table
    End Sub
สิ่งที่แตกต่างจากเดิม คือการเพิ่ม  DataSourceให้กับ dataGridView1 ของเรา เพียงเท่านี้  dataGridView1 ของเรา ก็สามารถแสดงตารางออกมาได้แล้ว
สิ่งเดียวที่เหลืออยู่ตอนนี้ คือการกำหนด Query Command ให้ถูกต้อง
จากในตัวอย่างโปรแกรม เราจะสังเกตุได้ว่า มีการเรียกใช้หลาย Column ภายใต้ หลาย Table ฉะนั้น สิ่งที่สำคัญ คือการทำให้ Query Command สามารถแสดงผลออกมาได้ โดยเรียกข้อมูลแต่ละ Table ออกมาให้ถูกต้อง
ข้อมูลที่เราจะเรียกออกมา มีดังนี้
Column
Table
StudentID
studentsubject
StudentName
student
SubjectID
studentsubject
SubjectName
subject
Score
studentsubject
การทำให้ คนละตาราง แสดงผลข้อมูลเดียวกันออกมาได้ วิธีการอย่างง่ายก็คือ ใช้ WHERE ในการกำหนดให้แต่ละตาราง แสดงข้อมูลเดียวกันออกมา เช่นตัวอย่างดังนี้
SELECT studentsubject.StudentID AS ID, StudentName AS Name, studentsubject.SubjectID, subject.SubjectName, Score
FROM studentsubject, subject, student
WHERE studentsubject.StudentID = ‘52113088-0’
AND studentsubject.SubjectID = subject.SubjectID
AND studentsubject.StudentID = student.StudentID
หรือพูดง่ายๆก็คือ การทำให้ PRIMARY ของแต่ละตาราง มีค่าเท่ากับ FORIEGN ของตารางกลางนั่นเอง
แต่ในการเขียนโค้ดจริงๆ เราจะต้องทำการเปลี่ยน จากค่าที่แน่นอนอย่างเช่นรหัสนักศึกษา ไปเป็นค่าของ Combobox.Text แทนเราจึงต้องแก้ไขโค้ด เป็นดังนี้
MySqlCommand cmd = newMySql.Data.MySqlClient.MySqlCommand(
    “SELECT studentsubject.StudentID as ID, “+
    “StudentName as Name, “ +
    “studentsubject.SubjectID, “ +
    “subject.SubjectName, “ +
    “Score “ +
    “FROM studentsubject, subject, student “+
    “WHERE studentsubject. StudentID = ‘” + StudentIDCombobox.Text + “‘ “ +
    “AND studentsubject.SubjectID = subject.SubjectID “ +
    “AND studentsubject.StudentID = student.StudentID”, Connection);
    Dim cmd As MySqlCommand = NewMySql.Data.MySqlClient.MySqlCommand( _
            “SELECT studentsubject.StudentID as ID, “& _
            “StudentName as Name, “ & _
            “studentsubject.SubjectID, “ & _
            “subject.SubjectName, “ & _
            “Score “ & _
            “FROM studentsubject, subject, student “ & _
            “WHERE studentsubject.StudentID = ‘”& StudentIDCombobox.Text & “‘ “& _
            “AND studentsubject.SubjectID = subject.SubjectID “ & _
            “AND studentsubject.StudentID = student.StudentID”, Connection)
ผลลัพท์ที่ได้
ซึ่งเราก็ต้องมีการค้นหาจาก SubjectID ด้วย ซึ่งจะทำเหมือนเดิมทุกอย่าง เพียงแค่เปลี่ยน StudentIDCombobox ใน cmd เป็น SubjectIDCombobox เท่านั้นเอง (ในโปรเจคตัวอย่าง จะรวมกันให้แล้วในอีกรูปแบบ เป็นการรวมในรูปแบบของ หลาย Control 1 Event)
ในการทำงานที่เหลือ ขอให้ไปศึกษาใน Project กันเอง แต่คิดว่าคงไม่ยาก เพราะส่วนใหญ่ยังคงเป็นการอัด Query เข้าไปเช่นเคยเหมือนที่ผ่านมา
 
Download Project
 
Download Database
มาเป็นไฟล์ .sql http://www.mediafire.com/?7hskz5oyq7cqkix

2 thoughts on “MySql with C#, VB .NET

  1. สวัสดีครับ คือผมอยากได้ code โดยการเลือก combobox หลายอันในการค้นหา อะครับ พอมีไหมครับผมจะทำงานส่งอาจารย์ก่อนจบครับ

  2. คือถ้ามาเป็น IP ของโฮสที่เช่ามาใส่ IP ไปเลยแล้วไม่ให้ Error ทำไงครับ

Leave a Reply

Your email address will not be published. Required fields are marked *