|
|
September 22 | Home Page | รายการบทความ | ลิงค์ที่เกี่ยวข้อง | laploy.com | เกี่ยวกับผู้เขียน ตัวอย่างเนื้อหาของหนังสือ เรีนรู้ด้วยตนเอง LINQ [ตอน2] ข้อดีของ LINQ ก่อนหน้าที่จะมี LINQ การพัฒนาซอฟต์แวร์ที่เกี่ยวข้องกับแหล่งข้อมูลคละแบบ ท่านจำเป็นต้องใช้ API (Application Programming Interface ตัวเชื่อมต่อกับโปรแกรมประยุกต์) ที่แตกต่างกันหลายแบบ แต่ละแบบมีเทคโนโลยีและวิธีใช้งานเป็นของตัวเอง ยกตัวอย่างเช่นเมื่อท่านติดต่อกับ SQL2008 ท่านต้องใช้ ADO.NET เมื่อจะติดต่อกับแฟ้มข้อมูล XML ท่านต้องใช้ API ที่อยู่ภายในเนมสเปส System.Xml สภาพการเช่นนี้สร้างความปวดเศียรเวียนเกล้าให้แก่กรรมกรซอฟต์แวร์กันทั่วหน้า เพราะวิธีเขียนโค้ดติดต่อกับข้อมูลมีโมเดลหลายแบบ ขาดความคงเส้นคงวา ดีใจได้! เพราะต่อไปนี้จะไม่เป็นเช่นนั้นแล้ว LINQ จะช่วยให้ท่านทำงานกับแหล่งข้อมูลทุกชนิดได้ด้วยวิธีที่เหมือนๆ กันหมด ความคงเส้นคงวาเช่นนี้ช่วยให้ชีวิตของกรรมกรซอฟต์แวร์สะดวกสบายขึ้นมาก เพราะเมื่อท่านชำชองวิธีติดต่อกับแหล่งข้อมูลชนิดหนึ่งแล้ว ท่านจะสามารถเขียนโค้ดติดต่อกับแหล่งข้อมูลชนิดอื่นได้โดยใช้ความรู้เดียวกัน ยกตัวอย่างเช่นเมื่อท่านช่ำชองวิธีคิวรีข้อมูลในอาร์เรย์ด้วย LINQ แล้ว ท่านจะสามารถคิวรีข้อมูลในฐานข้อมูลได้โดยไม่ต้องเรียนรู้วิธีทำใหม่ทั้งหมด เพราะนับว่าท่านได้เรียนแนวคิดแนวปฏิบัติที่สำคัญต่างๆ ใน LINQ ไปมิใช่เล็กน้อยแล้ว ข้อดีอีกอย่างหนึ่งของ LINQ คือนอกจากท่านจะไม่ต้องห่วงว่าคิวรีจะผิดไวยากรณ์ เพราะตัวแปลภาษาจะตรวจสอบ และแจ้งความผิดพลาดให้อย่างที่เรียนไปแล้ว ส่วนอินเทลลิเซนส์ (IntelliSense คุณสมบัติเพื่อตรวจสอบความถูกต้องและเสนอแนะคำที่เหมาะขณะป้อนพิมพ์โค้ดของ VS2008) ยังสามารถทำงานกับ LINQ ได้อย่างก้าวหน้า ช่วยให้การป้อนพิมพ์โค้ดทำได้อย่างสนุก เรื่องสำคัญที่ไม่ควรมองข้ามอีกประการหนึ่งคือ LINQ ไม่ได้ส่งผลกระทบต่อการทำงานกับข้อมูลเท่านั้น การผสาน LINQ เข้ากับ C# ยังทำให้ภาษา C# เปลี่ยนแปลงไปอย่างสู่รูปโฉมใหม่อีกด้วย วิธีเขียนโค้ดของท่านจะไม่เหมือนเดิมอีกต่อไปแล้ว เพราะในหนังสือเล่มนี้ท่านจะได้เรียนรู้วิธีใช้ประโยชน์จากความเปลี่ยนแปลงที่เกิดขึ้นอย่างกว้างขวางในภาษา C# ที่จะช่วยให้โค้ดของท่านสั้นกระชับแต่จะทรงพลังกว่าเดิม
ภาพ 1-6: ส่วนอินเทลลิเซนส์ (IntelliSense คุณสมบัติเพื่อตรวจสอบความถูกต้องและเสนอแนะคำที่เหมาะขณะป้อนพิมพ์โค้ดของ VS2008) ยังสามารถทำงานกับ LINQ ได้อย่างก้าวหน้า ชุดเครื่องมือ LINQ LINQ เหมือนเหรียญที่มีสองด้าน ในด้านหนึ่งมันเป็นชุดเครื่องมือเพื่อใช้ทำงานกับข้อมูล และในอีกด้านหนึ่งมันมีภาวะเป็นส่วนที่เพิ่มขยายความสามารถของภาษา C# ในหัวข้อนี้ผู้เขียนจะพูดถึง LINQ ในแง่ที่เป็นชุดเครื่องมือ ท่านอาจมองว่า LINQ เป็นกล่องเครื่องมือที่มีเครื่องมือมาให้หลายอย่างดังนี้ - LINQ to Object: เป็นเครื่องมือที่ช่วยให้ท่านทำคิวรีกับข้อมูลที่อยู่ภายในดาต้าคอลเลคชันภายในหน่วยความจำ
- LINQ to DataSet: เป็นเครื่องมือที่ช่วยให้ท่านทำคิวรีกับข้อมูลที่อยู่ภายในดาต้าเซต
- LINQ to SQL: เป็นเครื่องมือที่ช่วยให้ท่านทำคิวรีกับข้อมูลที่อยู่ภายในฐานข้อมูล
- LINQ to Entity: เป็นเครื่องมือที่ช่วยให้ท่านทำคิวรีกับข้อมูลที่อยู่ภายในออพเจ็กต์แบบ ADO.NET เอ็นทิตีเฟรมเวิร์ค
- LINQ to XML: เป็นเครื่องมือที่ช่วยให้ท่านทำคิวรีกับข้อมูลที่อยู่ภายในแฟ้มข้อมูล XML
ในหนังสือเล่มนี้ท่านจะได้เรียนเครื่องมือที่ LINQ มีมาให้ทั้งห้าแบบนี้โดยละเอียด เครื่องมือห้าแบบนี้บางทีเรียกว่าตัวให้บริการหรือโพรไวเดอร์ (LINQ Provider ย่อ LP) ลองพิจารณาภาพ 1-7 จะเห็นว่าส่วนบนสุดคือภาษาที่ใช้งานกับ LINQ ได้ (ขณะนี้มีเพียงสองภาษาคือ C# 3.0 และ VB 9.0) ระดับถัดลงไปจากภาษาคือส่วนเพิ่มขยายหรือเปลี่ยนแปลงภาษาเพื่อให้ใช้งาน LINQ ได้ ประกอบด้วยสิ่งหลักสามสิ่งคือ ตัวดำเนินการคิวรีมาตรฐาน (Standard Query Operators ย่อ SQO) นิพจน์คิวรี (Query Expression ย่อ QE) และนิพจน์ต้นไม้ (Expression Tree ย่อ ET) ถัดจากส่วนเพิ่มขยายหรือเปลี่ยนแปลงภาษาเพื่อให้ใช้งาน LINQ ได้คือ LP ประกอบด้วยตัวให้บริการห้าตัวคือ LINQ to Object, LINQ to XML, LINQ to SQL, LINQ to DataSet และ LINQ to Entities ในอนาคตทีมงานผู้สร้าง LINQ อาจเพิ่ม LP แบบใหม่ๆ ขึ้นอีกได้ กรอบล่างสุดคือแหล่งข้อมูลที่ใช้ทำคิวรี (Data Source ย่อ DS) โดย DS แต่ละแบบจะสัมพันธ์กับ LP แต่ละตัว โปรดทราบว่าส่วน LP ไม่ใช่โปรแกรมที่แยกต่างหากหรือปลั๊กอิน แต่เป็น นวัตกรรมที่ถูกผนวกไว้กับภาษาเขียน C# 3.0เลย ที่เป็นไปได้เช่นนั้นเพราะ NETFX และภาษา C# ถูกดัดแปลงต่อเติมเพื่อให้รองรับ LINQ ได้ดังจะอธิบายรายละเอียดในหัวข้อถัดไป เนื่องจาก DS แบบ RDBMS, DataSet และ ADO.NET Entity Framework ล้วนสัมพันธ์กับฐานข้อมูลดังนั้นเราจึงอาจจัด LP แบบ LINQ to SQL, LINQ to DataSet และ LINQ to Entities ไว้เป็นกลุ่มเดียวกันได้อย่างที่เห็นในภาพ 1-8
ภาพ 1-7: สถาปัตยกรรม LINQ ที่ประกอบด้วยส่วนหลักสี่ส่วนคือภาษาโปรแกรม ส่วนเพิ่มขยายหรือเปลี่ยนแปลงภาษาเพื่อให้ใช้งาน LINQ ได้ ส่วนตัวให้บริการ LINQ และแหล่งข้อมูล
ภาพ 1-8: เราอาจจัด LP แบบ LINQ to SQL, LINQ to DataSet และ LINQ to Entities ไว้เป็นกลุ่มเดียวกันได้ ความเปลี่ยนแปลงในภาษา C# การจะทำให้ภาษา C# ใช้งาน LINQ ได้ ฮาเยสเบิร์ก จำเป็นต้องเสริมเพิ่มสิ่งจำเป็นให้แก่ NETFX และภาษา C# การเพิ่มที่ว่านี้ไม่ใช่เป็นแค่เพียง “วากยสัมพันธ์แช่อิ่ม” (Syntactic sugar หมายถึงวากยสัมพันธ์ที่ไม่ได้เพิ่มความสามารถให้ภาษา แต่มีไว้เพื่อให้เขียนโค้ดได้สะดวกหรือสง่างามขึ้น) เพื่อให้ท่านคิวรีฐานข้อมูลในภาษา C# ได้สะดวกขึ้นเท่านั้น แต่เป็นการเพิ่มเติมที่ทำให้ท่านสามารถเขียน “โปรแกรมเชิงเจตจำนง” (Declarative Programming ย่อ DP) ได้ สาเหตุที่ต้องยุ่งเกี่ยวกับ DP เพราะภาษาเพื่อการคิวรีข้อมูลในฐานข้อมูลสัมพันธ์ที่นักเขียนโค้ดคุ้นเคยที่สุดคือภาษา SQL เป็นภาษาแบบ DP ซึ่งเน้นการระบุว่าต้องการผลลัพธ์อย่างไร มีหลักการคิดแตกต่างจากภาษา C# ที่เป็นภาษาเชิงกำหนด (Imperative Programming ย่อ IP) ซึ่งเน้นการระบุว่าต้องการให้ดำเนินการอย่างไร ในชั้นแรกส่วน DP ที่ถูกเพิ่มเข้าใน C# 3.0 มีเจตนาให้ใช้คิวรีข้อมูลเท่านั้น แต่ภายหลังแนวคิดนี้คลี่คลายออกครอบคลุมส่วนที่ไม่ใช่คิวรีด้วย ดังนั้นใน C# 3.0 นอกจากท่านจะสามารถเขียนโปรแกรมตามลัทธิ IP อย่างที่เคยปฏิบัติมาแต่เดิมแล้วท่านยังอาจเขียนโปรแกรมตามลัทธิ DP ได้อีกด้วย ต่อไปลองมาดูตัวอย่างสิ่งที่เพิ่มขึ้นในภาษา C# เพื่อให้คิวรีข้อมูลได้โดยใช้ LINQ สมมุติว่าท่านได้รับโจทย์ดังนี้ “จงคิวรีข้อมูลในตาราง Products ในฐานข้อมูล AdventureWork2008 เฉพาะแถวที่รหัสสินค้ามากกว่า 2 และชื่อสินค้านำหน้าด้วย A จากนั้นนำผลลัพธ์ที่ได้ไปใส่ในโครงสร้างแบบ XML ในหน่วยความจำ” โจทย์แบบนี้หากไม่ใช้ LINQ ท่านจะต้องเขียนโค้ดโดยใช้เทคโนโลยีสองอย่างผสมกัน คือใช้ ADO.NET เพื่อคิวรีฐานข้อมูล และใช้เนมสเปส System.Xml ของ NETFX เพื่อจัดการ XML แต่ถ้าใช้ LINQ โค้ดจะเป็นอย่างที่เห็นในภาพ 1-9
โค้ดในภาพ 1-9 บรรทัดที่ 13 ถึง 20 ทำหน้าที่คิวรีข้อมูลในตาราง Products ในฐานข้อมูล AdventureWork2008 เฉพาะแถวที่รหัสสินค้ามากกว่า 2 และชื่อสินค้านำหน้าด้วย A บรรทัดที่ 21 ถึง 29 ทำหน้าที่นำผลลัพธ์ไปใส่ในโครงสร้างแบบ XML ในหน่วยความจำ สิ่งที่เพิ่มขึ้นในภาษา C# 3.0 คือส่วน QE ในบรรทัดที่ 16 ถึง 20 จะเห็นว่ามีคำสั่ง from, where, orderby และ select หากนำโค้ดนี้คอมไพล์ใน C# 2.0 ท่านย่อมจะได้รับข้อความแจ้งความผิดพลาดเป็นจำนวนมาก ท่านจะได้เรียนรายละเอียดเกี่ยวกับ QE พร้อมเบื้องหน้าและเบื้องหลังอย่างพิสดารในบทต่อๆ ไป แต่ในหัวข้อนี้ผู้เขียนเพียงอยากจะให้ท่านตั้งข้อสังเกตว่าอันที่จริงแล้ว LINQ ไม่ใช่ภาษาใหม่ และ QE ก็ไม่ใช่ภาษาใหม่ด้วยเช่นกัน คิวรีที่ท่านเห็นในบรรทัดที่ 16 ถึง 20 แท้จริงแล้วเป็นภาษา C# โปรดตระหนักว่าบัดนี้ท่านสามารถคิวรีข้อมูลจากแหล่งข้อมูลอะไรก็ได้จากบรรทัดคำสั่งภาษา C# โดยตรง สภาพการเช่นนี้เป็นสิ่งที่กรรมกรซอฟต์แวร์ทุกผู้ทุกนามล้วนใฝ่ฝันมานานมิใช่หรือ ภาพ 1-9: โค้ดภาษา C# ใช้งาน LINQ เพื่อทำงานตามโจทย์ว่าจงคิวรีข้อมูลในตาราง Products ในฐานข้อมูล AdventureWork2008 เฉพาะแถวที่รหัสสินค้ามากกว่า 2 และชื่อสินค้านำหน้าด้วย A จากนั้นนำผลลัพธ์ที่ได้ไปใส่ในโครงสร้างแบบ XML ในหน่วยความจำ สาเหตุที่ต้อง LINQ จากตัวอย่างในหัวข้อที่ผ่านมาท่านอาจนึกอัศจรรย์ใจว่าเพราะเหตุใดเพียงแค่การคิวรีตารางแล้วจับผลลัพธ์มาใส่ XML ไมโครซอฟต์ถึงกับต้องดิ้นรนประดิษฐ์เทคโนโลยีใหม่อย่าง LINQ หรือทำไมหนังสือเล่มนี้ถึงมีเนื้อหายืดยาวมากนัก เพราะดูท่าว่า LINQ คงไม่มีสติอะไร หากท่านคิดเช่นนั้นโปรดอ่านหัวข้อนี้ หากท่านไม่ติดใจจะอ่านข้ามหัวข้อนี้ไปก็ยังได้ ในหัวข้อนี้ผู้เขียนจะอธิบายว่าการเชื่อมต่อกับแหล่งข้อมูลด้วยวิธีเก่ามีปัญหาอย่างไร และ LINQ เป็นทางออกของปัญหาอย่างไร ปัญหาของ ADO.NET ก่อนหน้ามี LINQ ท่านจะใช้ ADO.NET เพื่อติดต่อกับฐานข้อมูล แท้จริง ADO.NET เป็นเพียงไลบรารีพื้นฐานของดอตเน็ต (.NET Framework Class Library ย่อ FCL) คือเป็นชุด API อันประกอบด้วยคลาสต่างๆ เช่น SqlConnection, SqlCommand, SqlReader, DataSet และ DataTable ฯลฯ ปัญหาของการใช้คลาสเหล่านี้คือท่านจะต้องอ้างถึงตาราง คอลัมน์ และแถวข้อมูลโดยตรง และปรกติในฐานข้อมูลจะมีตารางและคอลัมน์จำนวนมาก การดึงข้อมูลออกจากตารางมาใส่ในหน่วยความจำและการใส่ข้อมูลที่แก้ไขแล้วกลับคืนเข้าไปในตาราง ท่านต้องเขียนรายการคอลัมน์ยืดยาว มีการประเมินว่าทีมนักพัฒนาเสียเวลาไปกับกิจกรรมเหล่านี้คิดเป็นร้อยละ 30 ถึง 40 ของเวลาทั้งโครงการ ปัญหาของการใช้ ADO.NET ไม่ได้หยุดอยู่เพียงเรื่องประสิทธิภาพในการพัฒนา แต่ยังลามไปถึงคุณภาพของงานด้วย บ่อยครั้งที่นักเขียนโค้ดเผอเรอกำหนดชนิดข้อมูลผิดต้องไล่หาบักอย่างยากลำบาก บางครั้งอาจไม่พบความผิดปรกตินี้จนกว่าจะใช้งานจริงไปสักพัก ภาพ 1-10 แสดงโค้ดที่ใช้ ADO.NET ติดต่อฐานข้อมูล AdventureWork2008 เพื่อคิวรีตาราง Products ไล่เรียงข้อจำกัดต่างๆ ได้ดังนี้ • บรรทัดที่ 11 ถึง 13 โค้ดกำหนดการเชื่อมต่ออยู่ในสภาพสตริง ตัวแปลภาษาจึงไม่รับรู้หากกำหนดค่าผิด • บรรทัดที่ 17 และ 18 เป็นคิวรีที่อยู่ในสภาพสตริง ตัวแปลภาษาจึงไม่รับรู้หากเขียนคิวรีผิด • บรรทัดที่ 25 และ 26 ผู้เขียนโค้ดไม่รู้ว่าข้อมูลที่รับมาเป็นไทป์อะไรเพราะส่วนอินเทลลิเซนส์ไม่สามารถแสดงคำแนะนำใดๆ ได้ • หากเปลี่ยนดาต้าเบสเซอฟเวอร์ (เช่นเปลี่ยนจากเซอฟเวอร์ที่ใช้ในการทดสอบไปเป็นเซอฟเวอร์ที่ใช้งานจริง) โค้ดนี้จะเออเรอร์ทันที นอกเสียจากว่าจะแก้ไขส่วนกำหนดการเชื่อมต่อเสียก่อน ภาพ 1-11 แสดงโค้ดที่ใช้ LINQ ติดต่อฐานข้อมูล AdventureWork2008 เพื่อคิวรีตาราง Products ไล่เรียงการแก้ปัญหาต่างๆ ได้ดังนี้ • บรรทัดที่ 40-14 การกำหนดการเชื่อมต่ออยู่ในสภาพออพเจ็กต์ที่ตัวแปรภาษารับรู้ • บรรทัดที่ 43-44 คิวรีทำในภาษา C# โดยตรง ตัวแปรภาษาตรวจสอบวากยสัมพันธ์ได้ • บรรทัด 49-30 เนื่องจาก r เป็นออพเจ็กต์ ส่วน ProductID และ Name มีภาวะเป็นพร็อพเพอร์ตีสมาชิกของ r อินเทลลิเซนส์จึงสามารถแสดงคำแนะนำได้ • หากเปลี่ยนดาต้าเบสเซอฟเวอร์ (เช่นเปลี่ยนจากเซอฟเวอร์ที่ใช้ในการทดสอบไปเป็นเซอฟเวอร์ที่ใช้งานจริง) ท่านไม่ต้องแก้ไขอะไรในโค้ดนี้เลย เพียงแต่เปลี่ยน O/RM ใหม่  ภาพ 1-10 โค้ดที่ใช้ ADO.NET ติดต่อฐานข้อมูล AdventureWork2008 เพื่อคิวรีตาราง Products  ภาพ 1-11 โค้ดที่ใช้ LINQ ติดต่อฐานข้อมูล AdventureWork2008 เพื่อคิวรีตาราง Products กรุณาติดตามตอนต่อไป 
| | Home Page | รายการบทความ | ลิงค์ที่เกี่ยวข้อง | laploy.com | เกี่ยวกับผู้เขียน
ตัวอย่างเนื้อหาของหนังสือ เรีนรู้ด้วยตนเอง LINQ [ตอน1] ซอฟต์แวร์คือการผสมผสานระหว่างโค้ดและข้อมูล การพัฒนาซอฟต์แวร์คือการเขียนโค้ดเพื่อดำเนินการกับข้อมูล ในการเขียนโค้ดมีภาษาโปรแกรมให้เลือกจำนวนมาก ท่านจะเลือกภาษาอะไรขึ้นอยู่กับปัจจัยต่างๆ หลายประการ อาทิ ลักษณะของงานที่จะนำไปใช้ ความถนัดของท่านหรือทีมผู้พัฒนา ระบบปฏิบัติการที่จะนำไปใช้ หรือนโยบายที่บริษัทหรือลูกค้ากำหนด แต่ไม่ว่าจะใช้ภาษาอะไรลงท้ายก็ต้องเขียนโค้ดซึ่งเกี่ยวข้องกับข้อมูลอยู่ดี โดยข้อมูลอาจอยู่ในแหล่งต่างๆ หลายแบบ อาทิ เป็นไฟล์ในดิสก์ เป็นตารางในฐานข้อมูล เป็นเอกสารแบบ XML ที่มาจากเว็บ หรือบ่อยครั้งที่ในงานๆ เดียวต้องพาดพิงแหล่งข้อมูลทุกแบบที่ว่ามานี้ผสมกัน กล่าวโดยถึงที่สุดแล้วไม่ว่าจะพัฒนาซอฟต์แวร์โครงการไหนมักหนีไม่พ้นจะต้องข้องเกี่ยวกับการจัดการข้อมูลในรูปแบบใดรูปแบบหนึ่งเสมอ เมื่อท่านพัฒนาซอฟต์แวร์ท่านย่อมคาดหวังว่าสภาพแวดล้อมจะเอื้ออำนวยให้ท่านจัดการข้อมูลได้ง่าย คือมีเครื่องมือ หรือมีตัวช่วย หรือมีไลบรารี ที่จะทำให้ท่านเข้าถึงแหล่งข้อมูลได้ง่าย ไม่ต้องพัฒนาสิ่งพื้นฐานเอาเองจากศูนย์ทั้งหมด หากท่านพัฒนาซอฟต์แวร์บนดอตเน็ตเฟรมเวิร์ค (Microsoft .NET Framework ย่อ NETFX) ท่านย่อมสบายใจได้ เพราะ NETFX จัดเตรียมกลไกที่เกี่ยวข้องกับการจัดการข้อมูลมาให้อย่างอุดมตั้งแต่เวอร์ชันแรก และยิ่งไปกว่านั้นในเวอร์ชัน 3.5 NETFX ได้จัดเตรียม LINQ ซึ่งช่วยผสานการจัดการข้อมูลเข้ากับภาษา C# ได้ใกล้ชิดขึ้นจนเป็นเนื้อเดียวกัน ก่อนที่จะมุ่งเข้าสู่เนื้อหาที่เป็นรายละเอียดต่างๆ เกี่ยวกับ LINQ ในบทนี้ท่านจะได้เห็นภาพมุมกว้างโดยทั่วๆ ไปของ LINQ เสียก่อน เพื่อให้รู้ว่าอะไรอยู่ที่ใด ซึ่งจะช่วยให้ท่านมองเห็นความสัมพันธ์ระหว่างส่วนต่างๆ ได้ชัดขึ้นเมื่อท่านเรียนถึงเนื้อหาส่วนรายละเอียด แนะนำ LINQ เบื้องต้น เมื่อท่านพัฒนาซอฟต์แวร์ด้วยภาษา C# ต้องมีจุดใดจุดหนึ่งในโปรแกรมที่ท่านจำเป็นต้องนำข้อมูลในออพเจ็กต์บันทึกลงไว้ในฐานข้อมูล กระทำคิวรีต่อฐานข้อมูล และนำข้อมูลจากฐานข้อมูลมาใส่ไว้ในออพเจ็กต์อีกรอบหนึ่ง ยกตัวอย่างเช่นท่านทำเว็บไซต์ขายสินค้า ท่านรับข้อมูลการสั่งซื้อมาเก็บไว้ในออพเจ็กต์ (หรือออพเจ็กต์คอลเลคชัน เช่นลิสต์ หรือดาต้ากริตวิว) จากนั้นนำข้อมูลนี้บันทึกลงสู่ตารางในฐานข้อมูลไมโครซอฟต์ SQL เซอฟเวอร์ 2008 (Microsoft SQL Server version 2008 ย่อ SQL2008) ในสมัยที่ยังไม่มี LINQ ท่านอาจทำทุกอย่างผ่านทางการเชื่อมต่อตามลัทธิ ADO.NET จากนั้นกระทำคิวรีกับฐานข้อมูลเพื่อดึงข้อมูลจากตารางต่างๆ มาผสมกันให้ได้เป็นธุรกรรมที่สมบูรณ์ แล้วนำข้อมูลสุดท้ายมาใส่ในออพเจ็กต์ (หรือออพเจ็กต์คอลเลคชัน เช่นดาต้าเทเบิล หรือดาต้ากริตวิว)เพื่อนำไปฉายแสดงให้ผู้ใช้ได้ดูชมบนหน้าเว็บ โชคดีที่ภาษา C# สนับสนุน OOP อย่างถึงที่สุด ทำให้ท่านพัฒนางานด้วยหลักการ OOP ได้ง่ายและได้อย่างเต็มที่ แต่โชคร้ายที่ตัวจัดการฐานข้อมูลสัมพันธ์ (Relational Database Management System ย่อ RDBMS) อย่าง SQL2008 ไม่เป็นเช่นนั้น นักพัฒนาพยายามทำฐานข้อมูลให้เป็นออพเจ็กต์โดยห่อหุ้มฐานข้อมูลไว้ในคลาส (Object/Relational Mapping ย่อ O/RM) โดยใช้เครื่องมือเท่าที่มีอยู่ในขณะนั้น ยกตัวอย่างเช่นบทที่ 11 ในหนังสือ “เรียนรู้ด้วยตนเอง OOP C# ASP.NET” (ISBN 13:978-974-212-598-1 ย่อ LOYOOP) ผู้เขียนสาธิตวิธีทำเช่นนี้ สภาพการก่อนมี LINQ การทำ O/RM ใน NETFX เวอร์ชันก่อน 3 แม้จะทำได้และใช้งานได้จริงแต่ก็ไม่สะดวก และมีจุดอ่อนที่ไม่สามารถนำโค้ดกลับมาใช้ใหม่ได้ซึ่งถือว่าเป็นเรื่องใหญ่ เพราะ Code Reusable คือหัวใจสำคัญของการเขียนโปรแกรมวัตถุวิธี หากจะแก้ให้ตรงประเด็นก็ต้องเปลี่ยนไปใช้ฐานข้อมูลแบบ OOP (Object-oriented Database Management System ย่อ ODBMS) โชคร้ายที่ในทางปฏิบัติทำไม่ได้ เพราะ ODBMS ไม่ได้รับความนิยม หน่วยงานต่างๆ ล้วนแล้วแต่ใช้ฐานข้อมูลแบบ RDBMS เช่น SQL2008, ออราเคิล PostgreSQL, DB2, MySQL ฯลฯ ด้วยกันทั้งสิ้น บริษัทไมโครซอฟต์รู้ว่าแนวทางของคอดด์นั้นดีเยี่ยมและผู้คนจะไม่เปลี่ยนใจไปจาก RDBMS ได้ง่ายนัก จึงจัดตั้งหน่วยงานขึ้นเพื่อค้นคว้าหาวิธีขจัดความยุ่งยากทางเทคนิคของการทำงานร่วมกันระหว่างฐานข้อมูลกับแอพลิเกชันที่พัฒนาด้วยภาษา C# ผลลัพธ์ที่ได้คือ LINQ ซึ่งช่วยให้การทำ OR/M ง่ายขึ้น โดยเฉพาะอย่างยิ่งหากท่านพัฒนาโดยอาศัย Visual Studio 2008 (VS2008) ท่านจะสามารถทำ OR/M ได้โดยไม่ต้องเขียนโค้ดแม้แต่บรรทัดเดียว เพียงลากและหยอด VS2008 จะผลิตโค้ดที่จำเป็นให้ได้อย่างครบถ้วน ความคิดดั้งเดิมของ LINQ คือต้องการให้การพัฒนาโปรแกรมภาษา C# ทำงานกับฐานข้อมูล SQL2008 ได้ง่ายขึ้นและเป็น OOP มากขึ้น เรียกว่า LINQ to ADO.NET แต่ต่อมาความคิดเกี่ยวกับ LINQ เริ่มคลี่คลายและขยายเป้าหมายออกไปกว้างกว่าตอนต้นมาก สุดท้าย LINQ กลายเป็นภาษาอเนกประสงค์ทำงานร่วมกับแหล่งข้อมูลได้สารพัด ยกตัวอย่างเช่น LINQ ที่ทำงานกับ SQL2008 เรียกว่า LINQ to SQL ส่วน LINQ ที่ทำงานกับแฟ้มแบบ XML เรียกว่า LINQ to XML และ LINQ ที่ทำงานกับออพเจ็กต์ เรียกว่า LINQ to Objects โปรแกรมจัดการฐานข้อมูลวัตถุวิธีหรือ ODBMS ไม่ได้รับความนิยม หน่วยงานต่างๆ ล้วนแล้วแต่ใช้ฐานข้อมูลแบบ RDBMS ภาพนี้คือโปรแกรม IBM DB2 Cube View 8.2 ขณะที่สตีเฟน ฮอว์กินส์ กำลังหาทางรวมทฤษฏีทั้งหมดเข้าด้วยกันให้เป็นทฤษฏีเดียวที่อธิบายได้ทุกอย่างในเอกภพหรือ มหาเอกะทฤษฏี (Grand Unified Theory ย่อ GUT) แต่ยังหาทางทำไม่สำเร็จ ทีมงาน LINQ กลับประสบความสำเร็จในการทำให้ LINQ สามารถทำงานร่วมกับแหล่งข้อมูลอะไรก็ได้ (Unified Data Source ย่อ UDS) ดังนั้นท่านจึงสามารถเขียนโค้ด (ที่มีซินแท็กซ์คล้ายๆ ภาษา SQL) เพื่อคิวรีข้อมูลภายใน SQL2008 ในลิสต์หรือแม้กระทั่งในแฟ้มข้อมูลตัวหนังสือได้โดยใช้วิธีการเดียวกัน เนื่องจากคิวรีที่ว่านี้เป็นภาษาที่กลืนเข้าเป็นเนื้อเดียวกันกับภาษา C# จึงเป็นที่มาของชื่อ LINQ (อ่านว่าลิ้งค์เหมือน Link) ย่อมาจากคำว่า Language INtegrated Query หมายถึงคิวรีที่ถูกบูรณาเข้ากับภาษาเขียนโปรแกรม (ขณะนี้สนับสนุนเฉพาะภาษา C# 3.0 แล VB.NET 9.0 ขึ้นไปเท่านั้น) คำว่าบูรณาการในที่นี้หมายถึงผสานเข้าด้วยกันอย่างไม่มีรอยต่อ เหมือนเป็นภาษาซ้อนในภาษา ยกตัวอย่างเช่นสมมุติว่าท่านต้องการคิวรีข้อมูลในตาราง Production.Product ของฐานข้อมูล AdventureWorks2008 หากทำในโปรแกรม Microsoft SQL Server Management Studio (SSMS) จะมีคิวรีและได้ผลลัพธ์อย่างที่เห็นในภาพ 1-2 หากเขียนเป็นโปรแกรมภาษา C# และเชื่อมต่อฐานข้อมูลด้วย ADO.NET โค้ดจะเป็นอย่างที่เห็นในภาพ 1-3 และผลลัพธ์เป็นอย่างภาพ 1-4 ภาพ 1-2: การคิวรีตาราง Production.Product ในฐานข้อมูล AdventureWorks2008 ด้วยภาษา T-SQL ภาพ 1-3: โค้ดภาษา C# แสดงตัวอย่างแสดงวิธีคิวรีข้อมูลในตาราง Categories ของฐานข้อมูล AdventureWorks2008 โดยใช้สถาปัตยกรรม ADO.NET ภาพ 1-4: ผลลัพธ์จากการทำงานของโปรแกรมในภาพ ado sample code โปรดสังเกตว่าโค้ดในภาพ 1-3 ส่วนที่เป็นคิวรีคือบรรทัดที่ 17 และ 18 ซึ่งอยู่ในสภาพสตริง ภาวะเช่นนี้ไม่ถือว่าคิวรีถูกบูรณาการเข้ากับภาษา C# เพราะตัวแปลภาษา C# และ CLR (Common Language Runtime) ไม่รับรู้ว่าสตริงนี้เป็นคิวรี ในทางตรงกันข้าม ตัวแปรภาษา C# จะไม่แปลคิวรีนี้และจะไม่ตรวจสอบว่าคิวรีมีไวยากรณ์ถูกต้องหรือไม่ และ CLR ก็จะไม่ให้หลักประกันในการทำงานและไม่อาจแสดงข้อความรันทามน์เออเรอร์ (Runtime Error Message ย่อ REM) ที่ถูกต้องตรงกับความเป็นจริงได้ ต่อไปลองมาดูตัวอย่างโค้ดภาษา C# ซึ่งทำหน้าที่เดียวกันและให้ผลลัพธ์เดียวกันทุกอย่าง แต่ใช้สถาปัตยกรรม LINQ บาง โค้ดเป็นอย่างที่เห็นในภาพ 1-5 คำว่า DataClasses1DataContext ในบรรทัดที่ 40 คือ O/RM ที่ผู้เขียนสร้างโดยการลากและหยอดไว้ก่อนแล้ว ส่วนที่เป็นคิวรีคือบรรทัดที่ 43 และ 44 โค้ดสองบรรทัดนี้เป็นส่วนหนึ่งของภาษา C# ดังนั้นตัวแปลภาษา C# จึงสามารถตรวจสอบได้ว่าเขียนผิดไวยากรณ์หรือไม่ และ CLR จะสามารถตรวจสอบความถูกต้องของไทป์ได้จึงแสดง RE ที่ถูกต้องตอนรันได้ ภาวะเช่นนี้ทำให้ LINQ เป็นคิวรีที่ถูกบูรณาเข้ากับภาษาเขียนโปรแกรมได้กลมกลืนเป็นเนื้อเดียวกัน ภาพ 1-5: โค้ดภาษา C# ซึ่งทำหน้าที่เดียวกันและให้ผลลัพธ์เดียวกันทุกอย่าง แต่ใช้สถาปัตยกรรม LINQ กรุณาติดตามตอนต่อไป 
| August 15 | Home Page | รายการบทความ | ลิงค์ที่เกี่ยวข้อง | laploy.com | เกี่ยวกับผู้เขียน
Reporting Services เคล็ดลับการทำรายงานจากฐานข้อมูล ลาภลอย วานิชอังกูร (laploy.com) โพสบล็อกตอนนี้จะขอเล่าประสบการณ์เมื่อผู้เขียนให้คำปรึกษาเกี่ยวกับ Business Intelligence ในหน่วยงานแห่งหนึ่ง แม้จะเป็นเหตุการณ์ที่ผ่านมานานแล้ว แต่บทเรียนย้งใช้ได้ดีอยู่จนถึงตอนนี้
Business Intelligence การใช้ BI มีมาหลายสิบปีแล้ว แต่ก่อนหน้าที่จะมีโปรแกรม MS-SQL การมีหรือการใช้ BI เป็นสิ่งที่ยุ่งยากและมีราคาแพง คงมีแต่หน่วยงานขนาดใหญ่เท่านั้นที่จะสามารถจัดหา BI มาใช้ได้ แต่การมาถึงของ SQL2008 ทำให้ทุกอย่างเปลี่ยนแปลงไป ปัจจุบันนี้หน่วยงานเล็กๆ ก็สามารถมี BI ใช้ได้ ใน SQL2008 มีส่วนที่เกี่ยวข้องกับ BI โดยตรงสามส่วนคือ Integration services (SSIS) ทำหน้าที่รวบรวมข้อมูลจากหลายๆ แหล่งเพื่อนำมาสังเคราะห์ให้อยู่ในรูปแบบที่นำไปใช้ได้อย่างมีประสิทธิภาพ , Analysis services (SSAS) ใช้สร้าโมเดลสำหรับการวิเคราะห์ข้อมูลเช่น Cube และ Subspace และ Reporting services (SSRS) ใช้สร้างรายงานแบบ OLAP ซึ่งเป็นส่วนที่ท่านจะได้เรียนโดยละเอียดในบทนี้และบทต่อไป หากท่านติดตั้งโปรแกรม Microsoft Visual Studio 2008 (MSVS2008) ไว้และติดตั้งโปรแกรม SQL2008 พร้อมส่วนเสริม BI ท่านจะสามารถใช้ MSVS2008 พัฒนางาน BI ได้ทั้งครบถ้วนทั่งสามแบบคือ SSIS, SSAS และ SSRS สถาปัตยกรรม "เอเลฟอง" (ชื่อสมมุติ) คือหน่วยงานหนึ่งที่ผู้เขียนทำหน้าที่ให้คำปรึกษา เอเลฟองเป็นบริษัทสัญชาติฝรั่งเศสที่มีสาขาหลายร้อยแห่งอยู่ในหลายประเทศทั่วโลก ในส่วนไอทีหน่วยงานนี้ใช้เทคโนโลยีของไมโครซอฟต์เป็นหลัก ส่วนฐานข้อมูลแบ่งออกเป็นสองส่วน ฐานข้อมูลที่ประมวลผลธุรกรรมการเงินใช้ออราเคิล และฐานข้อมูลที่ประมวลผลธุรกรรมในฝ่ายการผลิตใช้ไมโครซอฟต์ SQL เวอร์ชัน 2000 สาเหตุที่เอเลฟองใช้ดาต้าเบสเซอฟเวอร์เวอร์ชันเก่าขนาดนี้เพราะแอพลิเกชันที่ใช้อยู่ (ชื่อ Fx.Net) เป็นแอพลิเกชันที่พัฒนาขึ้นนานแล้ว โดยมีสำนักงานใหญ่ของเอเลฟองภาคพื้นเอเซียแปซิฟิก ว่าจ้างให้บริษัทใน "แบงกาลอร์" ทำหน้าที่ผลิตและดูแล Fx.Net เป็นแอพลิเกชันที่ถูกเขียนด้วยภาษา C# บนด็อตเน็ตเวอร์ชัน 1.1 และไมโครซอฟต์ SQL เวอร์ชัน 2000 เอเลฟองผลิตสินค้าแต่ละเดือนหลายแสนชิ้น ข้อมูลปริมาณมหาศาลที่เกิดจากขั้นตอนต่างๆ ในการผลิตสินค้าถูกเก็บรวบรวมไว้ในฐานข้อมูลอย่างเป็นระบบ นี่คือโกดังสะสมข้อมูลหรือ "ดาต้าแวร์เฮาส์" (Data warehouse) ที่นอกจากจะจำเป็นต้องใช้ในกระบวนการผลิตแล้ว ผู้บริหารระดับต่างๆ ยังหวังว่าจะสามารถนำข้อมูลเหล่านี้มาเรียบเรียงให้อยู่ในรูปแบบที่ทำให้เกิด "ความเฉียบแหลมทางธุรกิจ" (Business Intelligence หรือนิยมเรียกย่อว่า BI)
นิทานแห่งสองนาคร แน่นอนว่าการนำข้อมูลที่กระจัดกระจายอยู่ในตารางต่างๆ นับร้อย มาเรียงร้อยให้อยู่ในรูปแบบที่ผู้บริหารสามารถอ่านเข้าใจได้จำเป็นต้องอาศัยการทำ "รายงาน" ในรูปแบบต่างๆ ปัญหาหลักคือ Fx.Net ทำรายงานได้ไม่ดีนักเนื่องจากสาเหตุสองประการ ประการแรกคือการเกิดเออเรอร์แบบหมดเวลา (Query time-out error) ปัญหานี้เกิดจากโปรแกรม Fx.Net เรียกใช้เฟรมเวิร์คของเอเลฟองและสตอร์โปรซีเจอร์ (Stored procedure) ที่ถูกกำหนดไว้แล้วโดยศูนย์กำหนดทิศทางด้านไอที (ทีเซ็นเตอร์ T-Center) ของเอเลฟองที่สำนักงานใหญ่ในฝรั่งเศส บ่อยครั้งเมื่อรายงานต้องทำคิวรีข้อมูลปริมาณมากๆ จะเกิด time-out แต่ผู้พัฒนาซอฟต์แวร์ที่แบงกาลอร์ไม่สามารถปรับเปลี่ยนโครงสร้างหลัก เพื่อแก้ปัญหานี้ได้ตามอำเภอใจ ประการที่สองรูปแบบของรายงานไม่สวย คือเป็นเพียงเท็กซ์ ไม่สามารถใส่ตารางหรือแผนภูมิได้ ปัญหานี้เกิดจากโปรแกรม Fx.Net (รวมถึงเฟรมเวิร์คของเอเลฟอง) เป็นโปรแกรมที่ออกแบบมาให้ทำงานในระดับการผลิต (shop floor) จึงขาดคุณสมบัติที่จำเป็นต้องใช้เพื่อทำรายงานระดับบริหาร ทางเลือกที่สาม ทางเลือกในการแก้ปัญหานี้มีสามทาง แต่ละวิธีต่างก็มีข้อดีข้อเสียในตัวของมันเองทั้งสิ้นดังนี้ -
สร้างแอพลิเกชันรายงาน : วิธีนี้คือเขียนแอพลิเกชันขึ้นแยกต่างหาก (โดยไม่ขึ้นกับเฟรมเวิร์คของเอเลฟอง) โดยใช้ภาษา C# 3.0 ซึ่งมีคุณสมบัติเอื้ออำนวยการการทำคิวรีได้ในตัว ข้อดีของวิธีนี้คือจะสามารถทำรายงานที่มีรูปแบบพิสดารอย่างไรก็ได้ตามใจชอบ ข้อเสียของทางเลือกนี้คือใช้เวลาและค่าใช้จ่ายสูง -
ใช้โปรแกรม Crystal Report : คริสทัลรีพอร์ท (CR) เป็นโปรแกรมช่วยสร้างรายงาน ใช้งานง่าย มีประสิทธิภาพสูง สร้างรายงานที่ซับซ้อนมากๆ ได้โดยใช้เวลาสั้น ข้อเสียคือจะมีค่าใช้จ่ายในการซื้อมาใช้ และเป็นการเพิ่มเทคโนโลยีจากผู้ผลิตรายที่สามเข้าสู่ระบบ -
ใช้ Reporting Services : รีพอร์ทติง เซอร์วิสเซส (RS) แม้จะมีลูกเล่นน้อยกว่า CR แต่ก็มีคุณสมบัติใกล้เคียงกัน จึงมีข้อดีคล้ายกัน แต่ไม่มีข้อเสียเรื่องค่าใช้จ่าย (ฟรี คือแถมมาพร้อมกับตัว SQL เซอฟเวอร์) และความกังวลเรื่องเทคโนโลยีจากผู้ผลิตรายที่สาม แต่มีข้อเสียอื่นคือไม่สามารถทำรายงานที่ซับซ้อนมากๆ ได้ และขาดคุณสมบัติเพื่ออำนวยความสะดวกบางอย่าง (เช่น การป้อนพารามิเตอร์วันเวลาโดยแสดงส่วนติดต่อผู้ใช้เป็นปฏิทิน)
รายงานแบบ OLAP ทางเลือกต่างๆ ที่ว่ามาสามอย่างข้างต้นถูกนำมาพิจารณาอย่างรอบคอบ และพบว่ามันไม่สามารถแก้ปัญหาหลักอย่าง time out ได้ ทางออกคือการจัดตั้งเครื่องแม่ข่ายอีกเครื่องหนึ่งเพื่อใช้ทำเป็นฐานข้อมูล OLAP การทำเช่นนี้จะปลดเปลื้องภาระของแม่ข่ายธุรกรรมหรือ OLTP จากความหน่วงของคิวรีรายงานได้ทั้งหมด รายงานแบบ OLAP คือการวิเคราะห์ข้อมูลแบบออนไลน์ (Online Analytical Processing) OLAP ไม่ใช่แค่รายงานตายตัวแบบในกระดาษ แต่เป็นรายงานที่มีพลวัตและมีหลายมิติ ช่วยให้ผู้ใช้ได้รับข้อมูลที่ทันสมัยเพราะเปลี่ยนแปลงไปตามความเป็นจริง (real time) ในลักษณะต่างๆ เช่นตารางแสดงข้อมูลไขว้ (Pivot Table) หรือตารางแบบเมตริกซ์ (Matrix) ตารางรายงานที่ข้อมูลแปรผันได้ตามการป้อนเงื่อนไข (Report Parameter) รายงานที่เจาะลึกได้ (Drill Down) หรือรายงานที่โยงไปยังรายงานย่อยที่มีรายละเอียดอ้างอิงได้ (Drill through) เป็นรายงานบนหน้าจอที่มีปฏิสัมพันธ์กับผู้ใช้ หรือจะพิมพ์ลงกระดาษก็ได้ รายงานแบบ OLAP มักเป็นการวิเคราะห์ข้อมูลกับคลังข้อมูลหรือข้อมูลสะสม (data mining) เพื่อการทำนายแนวโน้ม เพื่อใช้เป็นเครื่องมือช่วยการบริหารและพัฒนากระบวนการต่างๆ ของธุรกิจให้มีประสิทธิภาพมากขึ้น อย่าสับสนระหว่าง OLAP กับ OLTP เพราะอย่างหลังคือการทำธุรกรรมออนไลน์ (Online Transaction Processing) ที่เป็นคนละเรื่องกัน ฐานข้อมูลของงาน OLTP จะมีขนาดเล็กกว่าและมีพลวัตสูง ส่วนฐานข้อมูลของ OLAP จะมีขนาดใหญ่กว่ามากแต่มีพลวัตต่ำหรือถึงกับไม่มีเลย การใช้เซิฟเวอร์อีกตัวทำเป็น OLAP มีข้อเสียอยู่ที่รายงานจะไม่ใช่ข้อมูลอัพเดตตามเวลาจริง แต่จะมีช่วงล้าสมัยเล็กน้อย ขึ้นอยู่กับว่าเราตั้งให้แม่ข่ายฐานข้อมูล OLTP คัดลอกข้อมูลในฐานข้อมูลมายังแม่ข่าย OLAP ถี่เพียงใด การกำหนดความถี่ต้องพิจารณาอย่างรอบคอบ เพราะถ้าทำถี่เกินไป (คือทุกชั่วโมง) อาจมีผลให้โหลดแม่ข่ายฐานข้อมูล OLTP มากเกินไป แต่ถ้าถี่น้อยไป (ทุกสัปดาห์) รายงานอาจล้าสมัยแล้ว ข้อดีของการทำรายงานด้วย SSRS ต่อไปนี้เป็นรายการแสดงข้อดีต่างๆ ของการทำรายงานด้วย SSRS -
ใช้เพลตฟอร์มมาตรฐาน: ไฟล์รายงานเป็นภาษา RDL จึงเป็นเพียงแท็กซ์ไฟล์ (text file) ธรรมดา เปิดด้วยแท็กซ์เอดิเตอร์อะไรก็ได้ หากใช้โปรแกรม MSVS2008 สร้างจะสะดวกมาก เพราะมีเครื่องอำนวยความสะดวกให้หลายอย่าง ไม่ต้องเขียนภาษา RDL ขึ้นเอง -
ค่าใช้จ่าย: SSRS แถมฟรีมากับ SQL2008 ดังนั้นหากท่านมีใบอนุญาตการใช้งาน SQL2008 ท่านจะสามารถใช้ SSRS ทำรายงานได้โดยไม่มีค่าใช้จ่ายอื่นเพิ่มเติมอีก -
ดูได้ทั่วโลก: เมื่อสร้างรายงานเสร็จและทำดีพลอยแล้วรายงานจะอยู่ในเว็บเซอฟเวอร์ ผู้ใช้สามารถใช้โปรแกรมเว็บเบราว์เซอร์เปิดดูได้พร้อมกันทุกคนจากทั่วโลก -
รายงานฝังตัว: ท่านอาจให้ผู้รับเปิดรายงานโดยใช้เว็บเบราว์เซอร์ หรือจะดึงรายงานไปฝังไว้เป็นส่วนหนึ่งของแอพลิเกชันที่ท่านสร้างไว้แล้วให้ผู้ใช้รายงานเปิดจากภายในแอพลิเกชันก็ได้ -
การรับรายงาน: รายงานที่ผู้ใช้เปิดเป็นรายงานสด ข้อมูลในรายงานเป็นข้อมูลที่อัพเดตตามเวลาจริงขณะนั้นๆ หรือท่านสามารถกำหนดให้ SSRS อัพเดตข้อมูลเฉพาะบางช่วงเวลาก็ได้ (เช่นอัพเดตวันละหนตอนตีสามเพราะเป็นเวลาที่ปริมาณการจราจรของข้อมูลคับคั่งน้อยที่สุด)
Crystal Report (CR) เป็นโปรแกรมประยุกต์แบบ BI จากบริษัท Business Object ซึ่งมีฐานะเป็นบริษัทลูกของ SAP โปรแกรม CR มีมานานแล้วแต่ไม่เด่นดัง จนกระทั่งไมโครซอฟต์นำมาผนวกไว้กับเครื่องมือพัฒนาโปรแกรมวิสชวลเบสิก ทำให้ CR เป็นที่รู้จักและกลายเป็นมาตรฐาน โดดเด่นกว่าโปรแกรมสร้างรายงานอื่นๆ ที่มีอยู่เป็นจำนวนมาก ในยุค MS-SQL 7 และ MS-SQL 2000 ผู้ที่ต้องการสร้างรายงานซับซ้อนสวยงามจำเป็นต้องนำ CR มาใช้ร่วมกับ MS-SQL เพราะ SSRS ในสมัยนั้นมีความสามารถที่จำกัด แต่พอถึงยุค SQL2005 และ SQL2008 สถานการณ์ก็เปลี่ยนไป เพราะ SSRS ถูกพัฒนาอย่างต่อเนื่องให้มีประสิทธิภาพสูงขึ้น แม้ SSRS จะมีความสามารถด้อยกว่า CR ในบางด้าน แต่ผู้ใช้ CR ร่วมกับ SQL2008 ก็เริ่มมีจำนวนลดลง เพราะในหลายๆ กรณี SSRS มีความสามารถเพียงพอที่จะตอบสนองความต้องการได้ และที่สำคัญคือผู้ใช้ไม่ต้องจัดซื้อ SSRS เพิ่มเติมเพราะมันถูกผนวกอยู่ใน SQL2008 ผู้ใช้จึงสามารถติดตั้งใช้งาน SSRS ได้ทันทีโดยไม่มีค่าใช้จ่ายเพิ่มเติม 
| August 14 |  Home Page | รายการบทความ | ลิงค์ที่เกี่ยวข้อง | laploy.com | เกี่ยวกับผู้เขียน
ดัชนีหนังสือ DabaBase [6] วันนี้ทำดัชนีหนังสือ DabaBase เสร็จเรียบร้อยแล้ว ขอนำมาโพสไว้ที่นี่ให้ดูเล่นหน่อยนะครับ
| ฐานข้อมูล | 48, 53 , 111, 141, 208, 333 | | ฐานข้อมูลเพื่อช่วยการตัดสินใจ | 79 | | ฐานข้อมูลแบบไคลเอนต์เซิร์ฟเวอร์ | 78 | | ฐานข้อมูลแบบคลังข้อมูล | 79 | | ฐานข้อมูลแบบผสมผสาน | 80 | | ฐานข้อมูลในงานธุรกรรม | 78 | | ฐานข้อมูลรายงาน | 79 | | ฐานข้อมูลสัมพันธ์ | 118 | | ดร. สตีฟ คุณน์ | 354 | | ดร. อี เอฟ คอดด์ | 65 | | ดรรชนี | 108, 210 | | ดอทเน็ตเฟรมเวิร์ก | 784 | | ดัชนี | 91, 208, 214, 218, 221, 224, 235, 313, 334 | | ดัชนีเผื่อเลือก | 210 | | ดัชนีแบบคลัสเตอร์ | 220, 312 | | ดัชนีที่ไม่เป็นคลัสเตอร์ | 226, 312 | | ดัชนีร่วม | 211 | | ดัชนีหลัก | 209 | | ดาต้าเซต | 61, 666 | | ดาต้าเบส | 48 | | ดาต้าเบสเซอฟเวอร์ | 185 | | ดาต้าเบสเอ็นจิน | 169, 182 | | ดาต้าเพจ | 211 | | ดาต้าโมเดล | 247 | | ดาต้าคอลเล็กชั่น | 506, 533, 542 | | ดาต้ารีเจียน | 667 | | ดีพลอยเมนต์ | 700 | | ต้นไม้ไบนารี | 108 | | ตรรกะ | 371, 417 | | ตรรกะบูลีน | 220 | | ตัวเรียงข้อมูล | 429 | | ตัวเลือกตอนเริ่ม | 195 | | ตัวเสริมโปรเจ็กชั่น | 430 | | ตัวแปร | 277, 278, 296, 362, 364, 487 | | ตัวแปร Global | 294 | | ตัวแปรแบบตาราง | 280, 649 | | ตัวแปรแบบอะนอนนิมัส | 861 | | ตัวแปรชี้แถว | 360 | | ตัวแปรชี้ทูเพิล | 360 | | ตัวแปรย่าน | 354 | | ตัวแปรสตริง | 610 | | ตัวแปลภาษา C# | 859 | | ตัวกระทำ | 325 | | ตัวกระทำฉายแสดง | 388 | | ตัวกำหนด | 122, 146 | | ตัวคงค่า | 454 | | ตัวจัดกลุ่ม | 429 | | ตัวจำกัด | 394 | | ตัวดำเนินการ | 380, 383, 387 | | ตัวดำเนินการเรียงข้อมูล | 433 | | ตัวดำเนินการจัดกลุ่ม | 431 | | ตัวดำเนินการตัดข้อมูลซ้ำ | 430 | | ตัวดำเนินการทางเซต | 407 | | ตัวดำเนินการบูลีน | 396 | | ตัวดำเนินการพีชคณิต | 390, 402 | | ตัวดำเนินการพีชคณิตเชิงสัมพันธ์ | 429 | | ตัวตั้ง | 401 | | ตัวตัดข้อมูลซ้ำ | 429 | | ตัวถูกดำเนินการ | 380 | | ตัวนับอัตโนมัติ | 62 | | ตัวประมวลผลแบบขนาน | 62 | | ตัวประมวลผลรายงาน | 736 | | ตัวหาผลรวม | 429 | | ตัวอย่าง | 402 | | ตารางเสมือน | 245, 557 | | ตารางแบบรีเลชั่น | 391 | | ตารางแม่ | 106, 336 | | ตารางแฮช | 210 | | ตารางไม่ผูกพัน | 107 | | ตารางช่วย | 245 | | ตารางชั่วคราว | 245, 469, 557 | | ตารางธุรกรรม | 133 | | ตารางผกผัน | 180 | | ตารางผูกพัน | 107 | | ตารางลูก | 106, 336 | | ตีนกา | 102 | | ทมยันตี | 223 | | ทรัพยากร | 90 | | ทริกเกอร์ | 577 | | ทูเพิล | 48, 354, 359, 391, 398, 400, 413, 423, 427, 434 | | ทูเพิลกำพร้า | 435 | | ทูลทิป | 523 | | ธุรกรรมแบบออนไลน์ | 56 | | นอร์มัลไลเซชั่น | 65, 88 , 91 , 118 | | นอร์มัลไลซ์ | 253 | | นอร์มัลฟอร์ม | 118 | | นอร์มัลฟอร์มแบบฉาย | 152 | | นอร์มัลฟอร์มแบบบอยซ์-คอดด์ | 125 | | นอร์มัลฟอร์มกุญแจโดเมน | 126 | | นอร์มัลฟอร์มระดับที่สอง | 125 | | นอร์มัลฟอร์มระดับที่สาม | 125 | | นอร์มัลฟอร์มระดับที่สี่ | 125 | | นอร์มัลฟอร์มระดับที่หนึ่ง | 125 | | นอร์มัลฟอร์มระดับที่ห้า | 126 | | นักเขียน | 110 | | นิพจน์ | 355, 438, 735 | | นิพจน์เงื่อนไข | 411 | | นิพจน์เชิงเส้น | 421 | | นิพจน์แคลคูลัส | 360 | | นิพจน์ซ้อนนิพจน์ | 384 | | นิพจน์ตารางร่วม | 341 | | นิพจน์บูลีน | 394 | | นิพจน์พีชคณิต | 371 | | นิยามกุญแจ | 108 | | นิยามกุญแจเอกลักษณ์ | 109 | | นิยามกุญแจนอก | 109 | | นิยามนอร์มัลฟอร์ม | 125 | | นิยายนักสืบ | 135 | | นิ้วมือชี้ | 450, 470 | | บลูเรย์ | 82 | | บิตแมป | 210 | | บูรณภาพของข้อมูล | 88, 90 | | บูรณภาพสัมพันธ์ | 114 | | บูรณภาพอ้างอิง | 437 | | บูลีน | 851 | | ปฏิสัมพันธ์กับผู้ใช้แบบรูปภาพ | 60 | | ประสิทธิภาพของดัชนี | 232 | | ปุ่มลัด | 183, 194 | | ผลคูณคาร์ทีเซียน | 393, 399, 412, 419, 421, 427 | | ผู้ให้บริการฐานข้อมูล | 56 | | ผู้ออกแบบฐานข้อมูล | 92 | | พจนานุกรม | 214 | | พอยน์เตอร์ | 216, 221, 235, 531 | | พันธ์ทิพย์ | 81 | | พารามิเตอร์ | 594, 611, 622, 626, 643, 725, 771, 863 | | พีชคณิต | 245, 386 | | พีชคณิตเชิงสัมพันธ์ | 380 | | พีชคณิตเชิงสัมพันธ์เพื่อแสดงข้อจำกัด | 436 | | พีชคณิตเชิงสัมพันธ์ภาคเซต | 405 | | พีชคณิตเชิงสัมพันธ์ภาคแบ็ก | 422 | | พีชคณิตกร | 509 | | ฟลอปปีดิสก์ | 82 | | ฟังก์ชัน | 305, 651, 771 | | ฟาเรนโฮต์ | 254 | | ฟิลด์ | 48 | | ภาษา C# | 357, 361, 493, 508, 608, 620, 640, 773, 792, 850 | | ภาษา QBE | 355 | | ภาษาเบสิก | 275 | | ภาษาซี | 274 | | ภาษาอัลฟา | 354 | | ภาษีมูลค่าเพิ่ม | 145 | | มหาวิทยาลัยแคลิฟอร์เนียวิทยาเขตเบิร์กลีย์ | 354 | | มัลติเทียร์ | 167 | | มูฮัมมัด บิน มูซา อัล-ควาริซมิ | 386 | | ย่อหน้า | 198, 297 | | ยูเนียน | 388, 391, 408, 412, 413, 415, 423, 425, 500 | | รหัสประจำแถว | 222 | | ร้อยละ | 344, 749 | | รายงาน | 735 | | รีเคอร์ชั่น | 492 | | รีเคอร์ซีฟ | 342, 497, 644 | | รีเคอร์ซีฟแบบไฮราร์คีย์ | 499 | | รีเลชั่น | 383, 384, 398, 405, 408, 413, 415, 418, 426, 427 | | ลงทะเบียน CLRR | 802 | | ลงทะเบียนตัวแปรระบบ | 794 | | ลบตาราง | 318 | | ลำดับการทำงาน | 372 | | ลิสต์ | 434 | | ลูกศร | 520 | | ลูกศรสี่ด้าน | 669 | | ลูป | 337 | | วรรณยุกต์ | 215 | | วันเวลา | 344 | | วากยสัมพันธ์ | 357, 387, 495, 574, 578 | | วิซาร์ด | 533 | | วิดีโอ | 84 | | วิทยาการสารสนเทศ | 54 | | วิธีเขียนคิวรีแบบออฟไลน์ | 197 | | วิธีสร้างกลุ่มใหม่ | 714 | | วินโดว์ฟังก์ชั่น | 562 | | วิว | 61, 371, 532, 572 | | วิววัตถุ | 61 | | สเกลาร์ | 277, 464, 641, 653 | | สกุลเงิน | 141 | | สตริง | 337, 771 | | สตาร์วอร์ส | 409 | | สถาปัตยกรรมแบบเน้นเซอร์วิส | 167 | | สถาปัตยกรรมไคลเอนต์/เซอฟเวอร์ | 163 | | สถาปัตยกรรมไคลเอนต์/เซอฟเวอร์สามชั้น | 166 | | สพร็อกซ์ | 543, 581, 600, 620, 631, 792 | | หน่วยในเซต | 245 | | หน้าต่างเครื่องมือ | 199 | | หนึ่งต่อศูนย์ | 209 | | หนึ่งต่อหนึ่ง | 209 | | หนึ่งต่อหลาย | 209 | | หลักการหาวิธีดีที่สุด | 512 | | ห้องสมุด | 223 | | องค์กร | 50 | | อนุประโยค | 362 | | ออพเจ็กต์ | 71, 91 , 610, 859 | | ออพเจ็กต์เอ็กซ์พลอเรอร์ | 183, 184 | | ออพเจ็กต์วิว | 575 | | ออฟไลน์ | 197 | | ออราเคิล | 96, 337 | | อะตอม | 251, 256 | | อะนอมาลิ | 119, 157 | | อะนอมาลิของการแทรกข้อมูล | 120 | | อะนอมาลิของการลบข้อมูล | 121 | | อะนอมาลิของการอัปเดตข้อมูล | 121 | | อะมีบา | 261 | | อัลกอรึทึม | 215 | | อาร์เรย์ | 64, 127, 253 | | อิทาเนียม | 54 | | อินเตอร์เซ็กชั่น | 408, 419 | | อินเตอร์เซ็กต์ | 388, 392, 417, 425, 426 | | อินเทล | 54 | | อินเทอร์เน็ตแอปพลิเคชั่น | 78 | | อินพุตพารามิเตอร์ | 623 | | อินสแตนซ์ | 169, 773 | | อีเมล | 176, 580 | | อีควิจอยน์ | 490 | | อุปกรณ์บันทึกข้อมูล | 84 | | ฮาร์ดแวร์ | 54, 698 | | ฮาร์ดดิสก์ | 50, 80 , 83 , 119, 131, 208 | | ฮีป | 221, 226 | | ฮีสโตแกรม | 511 |
| |  Home Page | รายการบทความ | ลิงค์ที่เกี่ยวข้อง | laploy.com | เกี่ยวกับผู้เขียน
ดัชนีหนังสือ DabaBase [6] วันนี้ทำดัชนีหนังสือ DabaBase เสร็จเรียบร้อยแล้ว ขอนำมาโพสไว้ที่นี่ให้ดูเล่นหน่อยนะครับ
| เครื่องมือช่วยวิเคราะห์คิวรี | 506 | | เครื่องหมาย -- | 200 | | เครื่องหมายดอกจัน | 362 | | เคอร์เซอร์ | 342, 451, 484, 491 | | เซต | 244, 257, 335, 340, 341, 356, 391, 405, 422, 423, 427, 428, 449 | | เซตย่อยทางแนวตั้ง | 396 | | เซตว่าง | 437 | | เซลเซียส | 254 | | เซอฟเวอร์ | 164 | | เซอฟเวอร์ฟาร์ม | 684 | | เซอร์วิส | 166, 177, 178 | | เซิร์ฟเวอร์ | 178 | | เต้าหู้ | 475 | | เทราไบต์ | 684 | | เทอร์นารี | 56 | | เธต้าจอยน์ | 398, 399, 414, 419, 428, 490 | | เนมสเปส | 610, 787 | | เพจ | 213, 312 | | เพจข้อมูล | 213 | | เพจดัชนี | 213 | | เพลย์สเตชั่น | 81 | | เมเนจโค้ด | 172, 785 | | เมตาดาต้า | 56, 805 | | เมธอด | 610, 851, 863 | | เมนเฟรม | 95 | | เรย์มอนด์ เอฟ บอยซ์ | 145 | | เรียงข้อมูล | 331, 627 | | เว็บเบราเซอร์ | 693 | | เว็บแอปพลิเคชั่น | 56, 173 | | เอ็กเซล | 180, 181 | | เอกซ์เทนท์ | 211, 312 | | เอ็นทิตี้ | 55, 249 | | เอ็นทิตี้อิสระ | 107 | | เออร์เรอร์ | 464 | | เอาต์พุตพารามิเตอร์ | 624 | | แคช | 514, 515, 707 | | แคลคูลัสเชิงสัมพันธ์ | 354 | | แคลคูลัสภาคแสดง | 354 | | แคลคูลัสภาคโดเมน | 355 | | แคลคูลัสภาคตาราง | 355 | | แคลคูลัสภาคทูเพิล | 354 | | แจ้งเตือน | 177 | | แถบไตเติ้ล | 201 | | แถว | 48 | | แถวข้อมูลกำพร้า | 466 | | แทรกแถว | 214 | | แบ็ก | 356, 422, 423, 425 | | แบตช์ | 302, 326, 521 | | แบบจำลองข้อมูลแบบวัตถุ | 71 | | แบบจำลองข้อมูลสำหรับธุรกรรม | 60 | | แบบจำลองฐานข้อมูลแบบเครือข่าย | 68 | | แบบจำลองฐานข้อมูลแบบวัตถุวิธี | 72 | | แบบจำลองฐานข้อมูลแบบวัตถุสัมพันธ์ | 72 | | แบบจำลองฐานข้อมูลสัมพันธ์ | 69, 70 , 146 | | แผนการคัดลอก | 174 | | แผนการทำงาน | 506 | | แผนการทำงานจริง | 514 | | แผนปลีกย่อย | 511 | | แผนภูมิต้นไม้ RAE | 416 | | แผนภูมิต้นไม้ของตัวประมวลผลคิวรี | 509 | | แผนภูมิวิเคราะห์การปฏิบัติงานของคิวรี | 237 | | แผนภูมิอีอาร์ | 55, 102, 135, 141, 146 | | แมทริกซ์ | 555 | | แอกริเกต | 291, 342, 343, 560 | | แอตทริบิวต์ | 48, 360, 383, 385, 389, 393, 394, 397, 400, 403, 410, 415, 418, 420, 428 | | แอปพลิเคชั่น | 60, 89 , 95 , 165, 592 | | แอสเซมบลี | 784 | | โกดังข้อมูล | 79 | | โครงสร้าง | 88 | | โครงสร้างแบบต้นไม้ | 208 | | โครงสร้างแบบต้นไม้ไบนารี | 108 | | โครสร้างต้นไม้ | 227 | | โจทย์ | 256 | | โซลิดสเตทดิสก์ | 82 | | โซลูชั่น | 663 | | โปรเจ็กชั่นลิสต์ | 433 | | โปรเจ็กต์ | 610 | | โปรแกรมจัดการฐานข้อมูล | 54 | | โปรแกรมประยุกต์ | 118 | | โปรแกรมวิเคราะห์คิวรี | 368 | | โปร่งใส | 60 | | โพรซีเยอร์ | 250 | | โมเลกุล | 251, 254, 256 | | โรเซนเบอร์เกอร์ | 73 | | โหนด | 211 | | โหนดที่ไม่ใช่ระดับใบ | 217 | | โหนดระดับใบ | 217 | | โหนดราก | 216 | | โหนดลูก | 216 | | โหมดแม่ | 216 | | ไคลแอนเซอฟเวอร์ | 165 | | ไคลแอนท์ | 164, 175, 693 | | ไบนารี | 56, 64 , 214 | | ไพรมารีคีย์ | 70 | | ไฟล์เก็บรายงาน | 662 | | ไวยากรณ์ | 452, 695 | | ไอโซเมอร์ | 254 | | ไอคอน | 520, 528, 535, 575 | | ไอบีเอ็ม | 83, 354, 386 | | ไฮราร์คีย์ | 499 | | กฎของเซต | 81 | | กฎของมัวร์ | 80 | | กฎทางธุรกิจ | 92, 93 , 94 | | กราฟแท่ง | 755 | | กราฟวงกลม | 756 | | การเขียนคิวรีแบบออฟไลน์ | 197 | | การเปลี่ยนชื่อ | 383, 418 | | การแบ่งคอลัมน์ | 252 | | การกระจายคำในไวยากรณ์ | 508 | | การคิวรี | 88 | | การคูณ | 389, 393 | | การจอยที่กำหนดเงื่อนไขได้ | 399, 414 | | การจอยน์ | 449, 465 | | การจอยน์แบ็ก | 428 | | การจอยน์แบบสมมาตร | 400 | | การจอยน์สามัญ | 413, 434 | | การฉายแสดงแถวข้อมูล | 324 | | การดึงซับเซตของแถว | 359 | | การดึงซับเซตของคอลัมน์ | 362 | | การตัดยอดข้อมูล | 174 | | การประมวลผลแบบขนาน | 81 | | การผูกแอกกริเกต | 509 | | การพาดพิง | 122 | | การพาดพิงเป็นวงรอบ | 124, 152 | | การพาดพิงทางอ้อม | 122 | | การพาดพิงบางส่วน | 124 | | การพาดพิงสมบูรณ์ | 123 | | การพาดพิงหลายค่า | 124 | | การรักษาความปลอดภัย | 171 | | การลบ | 389 | | การวิเคราะคิวรี | 506 | | การสแกนดัชนีแบบคลัสเตอร์ | 512 | | การหาร | 389, 400, 401 | | การอัปเดตข้อมูล | 88 | | กุญแจ | 209, 407 | | กุญแจเสนอ | 123, 145 | | กุญแจเอกลักษณ์ | 108, 109 | | กุญแจแทน | 109 | | กุญแจคลัสเตอร์ | 224 | | กุญแจนอก | 107, 209 | | กุญแจผสม | 131, 135, 136 | | กุญแจร่วม | 113 | | กุญแจหลัก | 107 | | ข้อบังคับ | 114 | | ข้อมูล | 53, 56 | | ข้อมูลแบบเวลา | 63 | | ข้อมูลกำพร้า | 121 | | ข้อมูลที่มีพลวัต | 133 | | ข้อมูลสถิต | 133, 138 | | คลัสเตอร์ | 53, 61 , 174, 214, 221 | | คลาส | 851 | | ความปลอดภัย | 572 | | ความสัมพันธ์ | 250, 380 | | ความสัมพันธ์แบบจำแนกได้ | 107, 135 | | ความสัมพันธ์แบบจำแนกไม่ได้ | 107, 112, 135, 136 | | ความสัมพันธ์แบบศูนย์และหนึ่ง | 105 | | ความสัมพันธ์แบบหนึ่งต่อหนึ่ง | 103 | | ความสัมพันธ์แบบหนึ่งต่อหลาย | 104, 112, 127, 132, 138, 140 | | ความสัมพันธ์แบบหลายต่อหนึ่ง | 134, 137, 138, 142, 144 | | ความสัมพันธ์แบบหลายต่อหลาย | 104, 139 | | คอดต์ | 246, 354, 383 | | คอมโพเนนท์ | 179 | | คอมไพล์ | 796 | | คอมมานด์ไลน์ | 796 | | คอลเลชั่น | 215 | | คอลเลชั่นภายใน (BIC) | 736 | | คอลัมน์ที่มีข้อมูลซ้ำกัน | 128, 131 | | คอลัมน์ผสม | 328 | | คาเมลเคส | 299 | | คาเมลโนเตชั่น | 642 | | ค่าโดยปริยาย | 195, 724 | | ค่าประเมิน | 512 | | คาร์ทีเซียน | 336, 341, 366 | | ค่าสะสม | 343 | | คำจาร์กอน | 95, 121, 126 | | คำสั่งเงื่อนไข | 282 | | คิวบ์ | 181, 550, 689 | | คิวรี | 53, 119, 139, 182, 196, 197, 201, 237, 250, 259, 316, 337, 340, 358, 363, 863 | | คิวรีเอดิเตอร์ | 199 | | คิวรีแบบประจำและแบบจร | 88 | | คิวรีซ้อนคิวรี | 451, 465, 470 | | คิวรีย่อย | 260, 341, 346, 446, 450, 464, 561 | | คิวรีย่อยเพื่อตรวจหาค่า | 456 | | คิวรีย่อยที่เกี่ยวพันกัน | 457 | | คิวรีย่อยที่ให้ค่าเป็นชุด | 456 | | คิวรีย่อยที่คืนค่าเดี่ยว | 453 | | คิวรีหลัก | 446, 464 | | คิวรีหลายชั้น | 445, 453, 464, 465, 480 | | คิวรีออปติไมเซอร์ | 510 | | คีย์เวิร์ด | 296 | | คุก ไร | 73 | | จอยน์ | 139, 334, 365, 369, 389, 397, 418, 452, 480 | | จอยน์สามัญ | 397 | | จาวา | 72, 246, 268 | | ชนิดข้อมูล | 62 | | ชนิดข้อมูลซับซ้อน | 64 | | ชื่อเล่น | 363, 470 | | ซอฟต์แวร์ | 54, 90 | | ซอร์สโค้ด | 796 | | ซับเซต | 358 | | ซับเซตทางแนวนอน | 395 | | ซับคิวรี | 446 | | ซานโฮเซ่ | 65 | | ซิกมา | 359 | | ซีเควล | 53 | | ซีเล็กชั่น | 411, 420, 421 | | ซีพียู | 54 |
|
|
|
|
|