การใช้ Parameters ในการสร้าง query string สำหรับใช้กับ MySql Connector Net C# เบื้องต้น

สวัสดีครับ วันนี้จะมาแนะนำการใช้ parameter เพื่อสร้าง query string สำหรับใช้ในโปรแกรมที่เขียนด้วย C#  และใช้ MySql Connector Net เบื้องต้นนะครับ

ความสำคัญของการใช้ parameter คือเพื่อป้องกันการโจมตีแบบ  SQL Injection ซึ่งเป็นการใส่ command เข้ามาพร้อมกัน query ที่ถูกสร้างขึ้น สังเกตุการส้าง query string ด้านล่างนี้นะครับ

[code language=”csharp”] string query = "SELECT * FROM recipe WHERE name = " + name;
[/code]

จะเห็นได้ว่าเราได้สร้าง query string ขึ้นมาจากการรวมข้อความกับตัวแปรที่ค่าในตัวแปรนั้นอาจจะเป็นอะไรก็ตามแต่ที่ผู้ใช้งานป้อนเข้ามาซึ่งอาจจะเป็น query ที่ใช้โจมตีเราด้วยก็เป็นไปได้ ดังนั้นถ้าเราใช้ parameter

[code language=”csharp”] string query = "SELECT * FROM recipe WHERE name = @name";
[/code]

ในส่วนของ parameter จะถูกมองว่าเป็นเพียงแค่ฟิลด์ข้อมูลเท่านั้น(หมายความว่าส่วนของ parameter จะไม่ถูก execute) ดังนั้นการใช้ parameter จึงป้องกัน SQL injection ได้

สำหรับการใช้ parameter กับ MySql Connector Net นั้นก็ไม่ได้ยากอะไร ก่อนอื่นขอแนะนำส่วนที่เกี่ยวข้องก่อน

  • MySqlCommand.Parameters เป็น collection ที่เก็บ instance ของ Parameter class
  • Parameter class เก็บข้อมูล parameter เพื่อให้ MySqlCommand ใช้
  • MySqlCommand.Parameters.AddWithValue(string parameterName, object value) สร้าง Parameter class พร้อมกับระบุชื่อและค่าของ parameter และเก็บเข้าสู่ Parameters collection

ทั้งหมดที่จำเป็นก็มีเพียงเท่านี้ จริงๆ แล้วเราสามารถกำหนดได้ถึง ชนิดข้อมูลและขนาดของ parameter ผ่านการสร้าง Parameter class จากนั้นก็ Add parameter class เข้าสู่ Parameters collection อีกที แต่จากการทดสอบพบว่าไม่ผลอะไรกับการที่ไม่ได้กำหนดชนิดและขนาดของข้อมูล(ตัวอักษรเก็บได้กว้างสูงสุดเท่าที่เรากำหนดไว้อยู่แล้ว ตัวเลขส่วนตัวทดสอบแล้วเจอ exception ตั้งแต่ข้อมูลเกินตัวแปร int) ดังนั้นใช้ AddWithValue จะสะดวกกว่า

อย่างแรกคือการสร้าง query string ที่ระบุข้อมูลเป็นชื่อ parameter ก่อน โดยชื่อ parameter นั้นให้เติม prefix “@” ไว้

[code language=”csharp”] string query = "SELECT * FROM recipe WHERE name = @name";
[/code]

ต่อไปก็ทำการเพิ่ม parameter ให้กับ Parameters collection โดยต้องระบุชื่อ parameter ให้ตรงกับค่าที่ต้องการ

ข้อสังเกตเล็กน้อยคือเราจะไม่สามารถเพิ่ม Parameter ที่มีชื่อเหมือนกับ Parameter ที่มีอยู่ก่อนใน Parameters collection ได้ หรือก็คือไม่สามารถตั้งชื่อ parameter ซ้ำกันได้นั่นเอง ต่อไปจะเป็นตัวอย่างต่างๆ ในการใช้ parameter นะครับ

ใช้แบบปกติ

ผมใช้ query เดียวภายใน method ไม่ได้เปลี่ยน query เพื่อรันภายใน method ต่อโดยใช้ MySqlCommand เดิมแต่อย่างใด

[code language=”csharp”] public bool Update(int ID, int quantity)
{
try
{
string query = "UPDATE recipe SET quantity = @quantity WHERE recipe_id = @id";

if (OpenConnection())
{
MySqlCommand cmd = new MySqlCommand(query, connection);
cmd.Parameters.AddWithValue("@quantity", quantity);
cmd.Parameters.AddWithValue("@id", ID);
cmd.ExecuteNonQuery();
CloseConnection();

return true;
}
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Message + Environment.NewLine + ex.StackTrace, "Error number : " + ex.Number,
MessageBoxButtons.OK, MessageBoxIcon.Information);

return false;
}

return false;
}
[/code]

ใช้ใน Loop

เนื่องจากเราไม่สามารถเพิ่ม parameter ที่มีชื่อซ้ำกันเข้าไปภายใน MySqlCommand.Parameters.Clear() ในการลบ parameter เดิมภายใน collection ออกและทำการเพิ่มเข้าไปใหม่ หรือเราสามารถเปลี่ยนค่า parameter ผ่าน index ตรงๆ เลยก็ได้เช่น MySqlCommand.Parameters[i].Value = value; หรือ MySqlCommand.Parameters[“@parameterName”].Value = value; แต่ผมขอเลือกใช้วิธีการลบ parameter เดิมออก (ด้านล่างนี้เป็นตัวอย่างจริงๆ)

[code language=”csharp”] public void testmethod(string name, List<string>[] data)
{
if (OpenConnection())
{
string query = "INSERT INTO some_table (name, id, value)" +
"VALUES(@name, @id, @value)";
MySqlCommand cmd = new MySqlCommand(query, connection);

for (int i = 0; i < data[0].Count; i++)
{
cmd.Parameters.AddWithValue("@name", name);
cmd.Parameters.AddWithValue("@id", data[0][i]);
cmd.Parameters.AddWithValue("@value", data[1][i]);
cmd.CommandText = query;
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
}
}
}
[/code]

จากตัวอย่างล่าสุดนี้สามารถปรับไปใช้แบบกำปรับค่า parameter ผ่าน index ก็ได้ ลักษณะจะเป็นประมาณนี้

[code language=”csharp”] public void testmethod(string name, List<string>[] data)
{
if (OpenConnection())
{
string query = "INSERT INTO some_table (name, id, value)" +
"VALUES(@name, @id, @value)";
MySqlCommand cmd = new MySqlCommand(query, connection);
cmd.Parameters.AddWithValue("@name", name);
cmd.Parameters.AddWithValue("@id", data[0][0]);
cmd.Parameters.AddWithValue("@value", data[1][0]);

for (int i = 0; i < data[0].Count; i++)
{
cmd.Parameters["@id"].Value = data[0][i];
cmd.Parameters["@value"].Value = data[1][i];
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
}
}
[/code]

2 ตัวอย่างล่าสุดสามารถเขียนในแบบอื่นๆ ได้อีกหลายแบบ สามารถดูรายละเอียดได้จาก MySqlCommand Members ทั้งหมดนี้ก็เป็นพื้นฐานการใช้ parameter กับ MySqlConnector net ครับ ถ้ามีคำถามหรือผมอธิบายอะไรผิดไป คอมเม้นบอกกันได้เลยนะครับ