คำชี้แจง: บทความนี้ตีพิมพ์ใน "แอปพลิเคชันคอมพิวเตอร์" เล่มที่ 23 ฉบับที่ 11
บทคัดย่อ: ในการพัฒนาระบบต่างๆ การใช้ Stored Procedure ถือเป็นนิสัยที่ดี ซึ่งไม่เพียงแต่นำคุณลักษณะต่างๆ เช่น ตารางชั่วคราว ฟังก์ชัน และเคอร์เซอร์มาด้วยเท่านั้น แต่ยังรวมถึง การดีบัก การอัพเกรด และการบำรุงรักษากลายเป็นเรื่องง่าย อย่างไรก็ตาม การเรียกโพรซีเดอร์ที่เก็บไว้เกือบทั้งหมดอยู่ในโหมดเดียวกัน และข้อแตกต่างที่สำคัญก็คือ พารามิเตอร์ของโพรซีเดอร์ที่เก็บไว้แต่ละโพรซีเดอร์แตกต่างกัน ดังนั้น เป็นไปได้หรือไม่ที่จะใช้วิธีการเพื่อรวมการเรียกโพรซีเดอร์ที่เก็บไว้ทั้งหมดและลดการเขียนโปรแกรมที่ไม่จำเป็น? จากการศึกษาฐานข้อมูล SQL Server และ ASP.NET เราได้ใช้วิธีการโทรแบบครบวงจร วิธีการนี้จำเป็นต้องระบุชื่อของขั้นตอนการจัดเก็บที่จะเรียกใช้เท่านั้น และระบุค่าพารามิเตอร์เฉพาะเมื่อทำการโทร เพื่อให้มีการจัดเก็บใด ๆ สามารถเรียกขั้นตอนได้
คำสำคัญ: ขั้นตอนการจัดเก็บ ตารางระบบ มุมมองโครงสร้างข้อมูล รหัสประจำตัวเอกสาร ADO.NET: ② รายงานผลสัมฤทธิ์ทางเทคนิคเชิงปฏิบัติ (เทคโนโลยี) สรุปการเรียนรู้เชิงทฤษฎีและการปฏิบัติทางสังคม (สังคมศาสตร์)
เรียกกระบวนงานที่เก็บไว้ในลักษณะเดียวกันใน .NET
บทคัดย่อ: การใช้ Stored Procedure เป็นนิสัยที่ดีในการพัฒนาโปรเจ็กต์ มันมีตารางชั่วคราว ฟังก์ชัน และเคอร์เซอร์ และการดีบัก การอัพเกรด และการบำรุงรักษาก็สามารถได้รับประโยชน์จากมันเช่นกัน อย่างไรก็ตาม การเรียกไปยัง Stored Procedure เกือบทั้งหมดก็มีรูปแบบเดียวกัน ความแตกต่างระหว่างพารามิเตอร์เหล่านี้คือพารามิเตอร์ของ Stored Procedure ทั้งหมด ดังนั้นเราสามารถเรียก Stored Procedure ในลักษณะเดียวกันได้แม้จะมีความแตกต่างกันและลดโค้ดโปรแกรมลงก็ตาม ชื่อโพรซีเดอร์ที่เก็บไว้และค่าของพารามิเตอร์ คุณไม่จำเป็นต้องสร้างพารามิเตอร์ด้วยตัวเอง คำสำคัญ: Stord Procedure, System table, Information Schema, ADO.NET
สรุป: ในการพัฒนาโครงการ คุณมักจะเรียก ขั้นตอนการจัดเก็บ อย่างไรก็ตาม การเรียกกระบวนงานที่เก็บไว้เกือบทั้งหมดจะอยู่ในรูปแบบเดียวกัน ความแตกต่างหลักอยู่ที่ประเภทและค่าของแต่ละพารามิเตอร์ที่สร้างขึ้น เป็นไปได้ไหมที่จะเรียกโพรซีเดอร์ที่เก็บไว้ทั้งหมดผ่านฟังก์ชันเดียว (หรือคลาส)? บทความนี้ใช้วิธีการโทรแบบรวมตามหลักการของการใช้ตารางระบบที่ฐานข้อมูลจัดเตรียมไว้ วิธีการนี้จำเป็นต้องระบุชื่อของขั้นตอนการจัดเก็บที่จะเรียกใช้เท่านั้น และระบุค่าพารามิเตอร์เฉพาะเมื่อทำการโทร เพื่อที่จะได้ สามารถเรียก Stored Procedure ได้
บทคัดย่อ: เราต้องเรียก Stored Procedure ของระบบฐานข้อมูลในระหว่างการพัฒนาโครงการ อย่างไรก็ตาม การเรียก Stored Procedure นั้นแทบจะเหมือนกัน ความแตกต่างที่สำคัญคือความแตกต่างระหว่างประเภทหรือค่าของพารามิเตอร์ เป็นต้น เราสามารถเรียก Stored Procedure ผ่านทาง ฟังก์ชั่น (หรือคลาส) ขึ้นอยู่กับตารางระบบที่จัดทำโดยระบบฐานข้อมูล เราเขียนคลาสเพื่อเรียกกระบวนงานเก็บไว้ ในบทความนี้ พารามิเตอร์เดียวที่คุณระบุคือชื่อของกระบวนงานที่เก็บไว้และ ค่าของพารามิเตอร์ทั้งหมดของขั้นตอนการจัดเก็บ
<คลาส DIV=ข้อความ4><B>1. บทนำ</B></DIV>
ในการพัฒนาระบบต่างๆ การใช้ Stored Procedure ถือเป็นนิสัยที่ดี ไม่เพียงแต่นำคุณสมบัติต่างๆ เช่น ตารางชั่วคราว ฟังก์ชัน และเคอร์เซอร์มาใช้เท่านั้น แต่ยังทำให้การดีบัก อัปเกรด และบำรุงรักษาง่ายขึ้นอีกด้วย ในระหว่างกระบวนการจัดเก็บข้อมูล สามารถประมวลผลข้อมูลแล้วส่งคืนได้ ซึ่งสามารถให้การวิเคราะห์และการควบคุมข้อมูลได้มากขึ้น ในการเรียกกระบวนงานที่เก็บไว้ เราพบว่าการเรียกกระบวนงานที่เก็บไว้เกือบจะอยู่ในรูปแบบต่อไปนี้:
1. ประกาศ SqlConnection
2. ประกาศ SqlCommand และตั้งค่าคุณสมบัติการเชื่อมต่อเป็นอินสแตนซ์ SqlConnection ที่เพิ่งประกาศ ตั้งค่า CommandName เป็นชื่อขั้นตอนที่เก็บไว้ และ CommandType เป็นขั้นตอนที่เก็บไว้
3. เพิ่มพารามิเตอร์ทั้งหมดที่จำเป็นสำหรับการเรียกขั้นตอนที่เก็บไว้ไปยังคอลเลกชันพารามิเตอร์ของอินสแตนซ์ SqlCommand ที่เพิ่งประกาศ 4 เรียกเมธอด ExecuteReader() ของ SqlCommand เพื่อรับชุดแถวที่ส่งคืนโดยกระบวนงานที่เก็บไว้
4. ประกาศ SqlDataAdapter และ DataSet ตั้งค่าคุณสมบัติ SelectCommand ของ SqlDataAdapter เป็นอินสแตนซ์ที่ประกาศใน 3 จากนั้นเรียกใช้เมธอด Fill เพื่อเติมแถวที่ส่งคืนที่ตั้งค่าลงในชุดข้อมูล
5. ปิดวัตถุ SqlConnection
6. เผยแพร่แต่ละอินสแตนซ์ของวัตถุที่ประกาศ (หมายเหตุ: 4 หมายถึงวิธีการแยกข้อมูลสองวิธี) ในระหว่างกระบวนการเรียกนี้ เราพบว่าการเรียกกระบวนการที่เก็บไว้เกือบทั้งหมดอยู่ในโหมดนี้ ความแตกต่างอยู่ในที่เก็บข้อมูลในขั้นตอนที่ 2 ชื่อกระบวนการที่แตกต่างกัน แตกต่างจากพารามิเตอร์ที่ใช้ในการเรียก Stored Procedure แต่ละครั้งในขั้นตอนที่ 3 โดยมีความแตกต่างในชื่อพารามิเตอร์ ทิศทาง ชนิดข้อมูล ความยาว ฯลฯ ดังนั้นมีวิธีใช้การเรียกโพรซีเดอร์ที่เก็บไว้ทั้งหมดหรือไม่? นั่นคือคุณจะต้องระบุชื่อกระบวนงานที่เก็บไว้เท่านั้นจากนั้นส่งค่าพารามิเตอร์ไปยังวิธีการเรียกเพื่อให้ทราบถึงการเรียกกระบวนงานที่เก็บไว้ จากนั้นใช้โครงสร้างข้อมูลบางอย่างเพื่อบันทึกชุดแถวที่ส่งคืน ค่าพารามิเตอร์ขาออก และ ประมวลผลค่าส่งคืน หลังจากศึกษาตารางระบบของ SQL Server แล้ว เราพบว่าแนวคิดนี้เป็นไปได้
2. ตารางระบบและมุมมองโครงสร้างข้อมูล
ฐานข้อมูลเชิงสัมพันธ์ เช่น SQL Server เก็บข้อมูลเมตาในฐานข้อมูลไม่ทางใดก็ทางหนึ่ง ใน SQL Server จะเป็นฐานข้อมูลระบบและตารางระบบ หลังจากติดตั้ง SQL Server แล้ว ฐานข้อมูลระบบสี่ฐานข้อมูลจะถูกสร้างขึ้นโดยอัตโนมัติ: master, model, msdb และ tempdb ฐานข้อมูลหลักคือคลังข้อมูลระดับระบบทั้งหมดใน SQL Server บัญชีเข้าสู่ระบบ การตั้งค่าคอนฟิกูเรชัน ขั้นตอนการจัดเก็บระบบ และการมีอยู่ของฐานข้อมูลอื่นๆ จะถูกบันทึกไว้ในฐานข้อมูลหลัก ฐานข้อมูล msdb เก็บข้อมูลตัวแทนการเซิร์ฟเวอร์ SQL เมื่อมีการกำหนดงาน ผู้ปฏิบัติงาน และการแจ้งเตือน งานเหล่านั้นจะถูกจัดเก็บไว้ใน msdb model เป็นเทมเพลตสำหรับฐานข้อมูลที่ผู้ใช้สร้างขึ้นทั้งหมด เมื่อสร้างฐานข้อมูลใหม่ ให้คัดลอกโมเดลและสร้างออบเจ็กต์ที่จำเป็น tempdb บันทึกวัตถุชั่วคราวใน SQL Server จอแสดงผลที่สร้างตารางชั่วคราวและขั้นตอนการจัดเก็บชั่วคราวตลอดจนระบบสร้างวัตถุชั่วคราวทั้งหมดใช้ tempdb [1] และแต่ละฐานข้อมูลก็มีตารางระบบของตัวเอง ตารางระบบเหล่านี้ใช้เพื่อจัดเก็บข้อมูลการกำหนดค่าและอ็อบเจ็กต์ จากตารางระบบเหล่านี้ เราสามารถรับข้อมูลเกี่ยวกับพารามิเตอร์ทั้งหมดของแต่ละขั้นตอนการจัดเก็บ ข้อมูลนี้ถูกเก็บไว้ในตาราง syscolumns มีชื่อพารามิเตอร์ ประเภท ความยาว ทิศทาง ฯลฯ ที่ต้องใช้ในวิธีการของเรา อย่างไรก็ตาม ฟิลด์ในตารางระบบจะเปลี่ยนไปตามเวอร์ชันของ SQL Server ตัวอย่างเช่น type และ xtype ใน syscolumns เป็นตัวอย่างของการเปลี่ยนแปลงดังกล่าว ทั้งคู่เก็บข้อมูลประเภท เพื่อปรับวิธีการของเราให้เข้ากับการเปลี่ยนแปลงเวอร์ชันของ SQL Server เราจำเป็นต้องใช้มุมมองโครงสร้างข้อมูล ANSI-92 กำหนดมุมมองโครงสร้างข้อมูลเป็นชุดของมุมมองที่ให้ข้อมูลระบบ ด้วยการใช้ประโยชน์จากมุมมองนี้ คุณสามารถซ่อนตารางระบบจริงจากแอปพลิเคชันของคุณได้ การเปลี่ยนแปลงตารางระบบจะไม่ส่งผลกระทบต่อแอปพลิเคชัน ดังนั้นแอปพลิเคชันจึงสามารถเป็นอิสระจากผู้จำหน่ายฐานข้อมูลและเวอร์ชันได้ [1] รองรับ ANSI-92 และ SQL Server โดยใช้โครงสร้างการตั้งชื่อสามส่วนเพื่ออ้างอิงวัตถุบนเซิร์ฟเวอร์ภายในเครื่อง คำศัพท์เฉพาะทางของ ANSI-92 เรียกว่า Catalog.schema.object ในขณะที่ SQL Server เรียกมันว่า Database.owner.object [1] ตัวอย่างเช่น หากเราต้องการค้นหาข้อมูลพารามิเตอร์ทั้งหมดของขั้นตอนการจัดเก็บทั้งหมด เราสามารถใช้: เลือก * จาก INFORMATION_SCHEMA.PARAMETERS หากเราต้องการค้นหาข้อมูลพารามิเตอร์ทั้งหมดของขั้นตอนการจัดเก็บบางอย่าง ก็คือ: เลือก * จาก INFORMATION_SCHEMA.PARAMETERS โดยที่ SPECIFIC_NAME ='Proc1 ' ด้วยมุมมองโครงสร้างข้อมูล ปัญหามากกว่าครึ่งหนึ่งของเราได้รับการแก้ไขแล้ว ต่อไปเราจะมาดูวิธีการนำวิธีการของเราไปใช้ใน .NET
3. จุดเน้นของวิธีการนำไปใช้คือวิธีการรับข้อมูลพารามิเตอร์ทั้งหมดของขั้นตอนการจัดเก็บตามชื่อ จากนั้นจึงสร้างพารามิเตอร์แต่ละรายการโดยอัตโนมัติตามข้อมูลพารามิเตอร์เหล่านี้ เพื่อให้การดำเนินการเหล่านี้เป็นไปโดยอัตโนมัติ กระบวนการประกาศ SqlConnection, SqlCommand และ SqlParameter และกระบวนการสร้าง SqlParameter แต่ละรายการควรจะไม่ปรากฏแก่ผู้ใช้ สิ่งเดียวที่ผู้ใช้ต้องระบุคือชื่อของขั้นตอนการจัดเก็บ จากนั้นจึงระบุพารามิเตอร์ต่างๆ เมื่อโทร และไม่จำเป็นต้องระบุประเภทด้วย
3.1 การรับและสร้างพารามิเตอร์ของกระบวนงานที่เก็บไว้ วิธีการรับและสร้างพารามิเตอร์ของกระบวนงานที่เก็บไว้ที่จะเรียกเป็นจุดสำคัญ เราสามารถนำขั้นตอนนี้ไปใช้โดยอัตโนมัติผ่านมุมมองโครงสร้างข้อมูล
// รับและสร้างพารามิเตอร์ของโพรซีเดอร์ที่เก็บไว้
Private void GetProcedureParameter(พารามิเตอร์ params object[])
{ SqlCommand myCommand2 = new SqlCommand();
myCommand2.Connection
= this.myConnection;
= '" + this.ProcedureName + "' เรียงลำดับตาม ORDINAL_POSITION";
SqlDataReader reader = null; reader = myCommand2.ExecuteReader(); // สร้างพารามิเตอร์ส่งคืน
myParameter = new SqlParameter();
myParameter.ParameterName = "@Value";
myParameter SqlDbType = SqlDbType.Int;
myParameter.Direction = parameterDirection.ReturnValue;
myCommand.Parameters.Add(myParameter);
// สร้างแต่ละพารามิเตอร์ได้ที่นี่
ในขณะที่ (reader.Read())
{
myParameter = new SqlParameter();
myParameter.ParameterName = reader["PARAMETER_NAME"].ToString();
myParameter.Direction = reader["PARAMETER_MODE"].ToString()=="IN" ?ParameterDirection.Input:ParameterDirection.Output;
switch(reader["DATA_TYPE"].ToString()) {
case "int" :
if(myParameter.Direction == ParameterDirection.Input)
myParameter.Value = (int)parameters[i] ;
myParameter.SqlDbType = SqlDbType.Int;
break; //...การ
ประมวล
ผลประเภทเฉพาะจำนวนมากถูกละไว้
: break; }
i++
;
3.2 ส่งกลับชุดข้อมูลผลลัพธ์ ค่าส่งคืน และชุดพารามิเตอร์ขาออก หลังจากสร้างพารามิเตอร์ของกระบวนงานที่เก็บไว้แล้ว เราก็สามารถเรียกขั้นตอนที่เก็บไว้ได้ เนื่องจากใน .NET คลาสที่ใช้กันทั่วไปที่ส่งกลับชุดผลลัพธ์คือ SqlDataReader และ DataSet และ SqlDataReader สามารถใช้ได้ในขณะที่รักษาการเชื่อมต่อไว้เท่านั้น แต่ DataSet ไม่ได้ใช้ ในการใช้งานของเรา การเชื่อมต่อควรถูกตัดการเชื่อมต่อหลังการโทร ดังนั้นชุดข้อมูลจึงถูกใช้เพื่อบันทึกชุดผลลัพธ์ที่ส่งคืน
public SqlResult Call(พารามิเตอร์ params object[]){ // SqlResult เป็นคลาสที่กำหนดด้วยตนเองซึ่งใช้ในการบันทึกชุดข้อมูลผลลัพธ์ ค่าที่ส่งคืน และชุดพารามิเตอร์ขาออก SqlResult result = new SqlResult(); // กำหนดการเชื่อมต่อของคุณเองเป็น จำเป็นต้องใช้ String
myConnection = new SqlConnection(ConnectionString);
myCommand = new SqlDataAdapter(myCommand.Open();
myCommand.CommandType
=
CommandType.StoredProcedure;
จัดเก็บพารามิเตอร์ของขั้นตอนและตั้งค่า
GetProcedureParameter(parameters);
myAdapter.Fill(result.dataSet, "Table"); // รับค่าพารามิเตอร์ขาออกและคู่ชื่อของขั้นตอนที่เก็บไว้และบันทึกไว้ใน Hashtable GetOutputValue(); // ปล่อยทรัพยากรต่างๆ ที่นี่ และยกเลิกการเชื่อมต่อ
myAdapter.Dispose();
myCommand.Dispose()
;
myConnection.Dispose()
;
4. การทำงานเพิ่มเติม แม้ว่าการใช้งานของเราที่นี่มีไว้สำหรับฐานข้อมูล SQL Server แต่วิธีนี้สามารถใช้กับฐานข้อมูลใดๆ ที่ให้มุมมองโครงสร้างข้อมูล สอดคล้องกับมาตรฐาน ANSI-92 หรือให้ข้อมูลเมตา เรารวมมันไว้ในคลาส SqlProcedure และสามารถเรียกโพรซีเดอร์ที่เก็บไว้ได้อย่างง่ายดายเมื่อจำเป็น ซึ่งช่วยลดงานโค้ดที่ซ้ำซ้อนโดยทั่วไปได้มาก เพื่อให้คลาส SqlProcedure รองรับชนิดข้อมูลมากขึ้น ในเมธอด GetProcedureParameter() คุณต้องวิเคราะห์ประเภท ทิศทาง ความยาว ค่าเริ่มต้น และข้อมูลอื่น ๆ ของแต่ละพารามิเตอร์ตามความต้องการของคุณ จากนั้นจึงสร้างพารามิเตอร์นี้ โดยพื้นฐานแล้วทุกประเภทสามารถนำไปใช้ได้ แม้กระทั่งประเภทรูปภาพก็สามารถสร้างได้ด้วยวิธีนี้ วิธีนี้ทำให้ชั้นเรียนมีความทั่วไปและมีประโยชน์ในทุกโปรเจ็กต์
อ้างอิง
(1) Ray Rankins, Paul Jensen, Paul Bertucci, หนังสือเชิงปฏิบัติ SQL Server 2000, ปักกิ่ง: สำนักพิมพ์อุตสาหกรรมอิเล็กทรอนิกส์, 2545
[2] ห้องสมุด MSDN มกราคม 2546, Microsoft Corporation
เกี่ยวกับผู้แต่ง: Liu Zhibo (1979-) ชายจาก Xinhua, Hunan, ปริญญาโท, ทิศทางการวิจัยหลัก: โครงข่ายประสาทเทียมและการจดจำรูปแบบ, ระบบข้อมูลอัตโนมัติในสำนักงาน
อีเมล: [email protected]