วันพุธ, กรกฎาคม 14, 2553

ทิป เว็บเซอร์วิส : ลดปริมาณการรับ-ส่งข้อมูลบนเครือข่าย (Minimize traffic)

การเรียกเซอร์วิสข้ามระหว่างโพรเซส จะเป็นการสิ้นเปลืองทรัพยากรระบบมาก ดังนั้นเราควรลดจำนวนของ การสัญจร ข้อมูล
ที่วิ่งผ่าน ระหว่าง ตัวเว็บเซิอร์วิส และ ตัวที่ขอใช้บริการของมัน
แนะนำให้เลือกใช้เพียง ไม่กี่เว็บเมทธอด (จำนวนน้อย) สำหรับการส่งคืนค่าข้อมูลจำนวนมาก แทนเว็บเมทธอดหลายๆ ตัว ในการส่งคืนค่าข้อมูลอันจำกัด หรือข้อมูลที่ยังไม่สามารถนำมาใช้ได้
ดังนั้น ควรหลีกเลี่ยง การเรียกเว็บเมทธอดบ่อยครั้ง ในกรณีที่เราสามารถ นำผลลัพธ์อย่างเดียวกันออกมาได้โดยใช้เพียง เว็บเมทธอดเดียว สำหรับส่งคืนข้อมูลจำนวนมากได้

วันอังคาร, กรกฎาคม 13, 2553

ทิป เว็บเซอร์วิส : เรียกใช้เว็บเมทธอดแบบ asynchronous เท่าที่เป็นไปได้

การเรียกแบบ Asynchronous เป็นแนวคิดที่ดี สำหรับเว็บเมทธอด ซึ่งช่วยเพิ่มประสิทธิภาพเวลาประมวลผลได้อย่างดี
และแอพพลิเคชั่น ที่ขอใช้บริการ จะมีความยืดหยุ่น ในการทำงาน ในขณะที่มันรอการตอบกลับจากเว็บเซอร์วิส

วันจันทร์, กรกฎาคม 12, 2553

ทิป เว็บเซอร์วิส : กำหนดค่าเวลาสิ้นสุด (timeouts) ขณะเรียกใช้ synchronous

เว็บเมทธอด ควรจะตั้งค่า timeouts แทรกไว้ด้วย เพื่อป้องกันกรณี ที่มันทำงานค้างหรือ ประมวลผลคำสั่งผิดปกติที่
กินเวลานาน วิธีนี้ช่วยหลีกเลี่ยง ไม่ให้ไคลเอ็นต์แอพพลิเคชั่น ทำงานค้างไม่สิ้นสุด ในขณะรอการเรียกคืน ในเว็บเซอร์วิส
นอกจากนั้น เราสามารถตั้งค่า พร๊อพเพอร์ตี้ Timeout บน proxy class สำหรับไคลเอ็นต์เว็บเซอร์วิสได้
เว็บเซอร์วิส proxy class ได้พัฒนามาจาก คลาสหลักร่วมกัน ที่มีชื่อว่า WebClientProtocol ซึ่งมันได้จัดเตรียมค่า
พร๊อพเพอร์ตี้ timeout ที่กำหนดไว้

ตัวอย่าง :
Dim objWS As localhost.Northwind = New localhost.Northwind() ' Proxy Class
objWS.Timeout = 15000 ' ตั้งเวลาสิ้นสุดให้กับเว็บเมทธอดที่ 15 วินาที

การ แคชเนื้อหา เฉพาะส่วน (Fragment)

การแคชเนื้อหา บางส่วน เป็น ขั้นตอน การแคชเฉพาะส่วนของ ยูสเซอร์คอนโทรล ซึ่งเป็น ส่วนประกอบของเพจ ด้วยการแยก
ประมวลผลคำสั่ง ช่วยให้เราสามารถ แบ่งแยกเนื้อหาออกเป็นหน่วยย่อยหลายหน่วย และพักไว้ในหน่วยความจำ สำหรับส่วนอื่นๆ
ของเพจ ที่รองรับยูสเซอร์คอนโทรลสามารถ ประมวลผลคำสั่ง ได้ตามปกติ

เรานำ ไดเรกทีฟ OutputCache มาใช้โดยแทรก ไว้ภายในเพจ และยูสเซอร์คอนโทรล เนื่องจากมันจะช่วยแปลงค่าเนื้อหา
เพื่อพักข้อมูลเก็บไว้ในหน่วยความจำเครื่อง โดยไม่ต้องประมวลโค้ดคำสั่งของเพจะหรือยูเซอร์คอนโทรลใดๆ เมื่อมีการเรียกคำสั่งใหม่ และ วิธีดังกล่าวนี้ จะช่วยให้สามารถประหยัด การใช้ทรัพยากรระบบได้อย่างดี เพราะมันจะดึงข้อมูล มาจากหน่วยความจำ แทนที่จะไปดึงข้อมูลผ่านการประมวลโค้ดคำสั่ง และการประกาศค่าออปเจ็กต์ที่เกี่ยวข้อง เหมือนตอนเริ่มใช้งาน

การแคช ยูสเซอร์คอนโทรล ทำงานเหมือนกับ การแคชเพจ โดยแทรกไดเรกทีฟ OutputCache ถัดจาก คอนโทรลไดเรกทีฟ

วันศุกร์, กรกฎาคม 09, 2553

การแสดงค่า(Rendering) HTML อย่างมีประสิทธิภาพ

เคยสังเกตุว่าไหม เราไม่อาจที่จะเชื่อมต่อสตริงได้โดยง่าย ผ่าน เมทธอด Render()ภายในเซิร์ฟเวอร์คอนโทรล และส่งค่าไปยัง HtmlWriter เนื่องจาก การเชื่อมต่อสตริง (string concatenation) จะใช้โพรเซส ในส่วนของ การทำงานของทรัพยากรระบบมาก โดยเฉพาะอย่างยิ่ง หากเราจะต้อง เชื่อมสตริงจำนวนมาก และทำมันในหลายๆ ครั้งในเพจหนึ่ง สำหรับแสดงผลในคอนโทรลหนึ่ง การใช้ ออปเจ็กต์ StringBuilder เพื่อทำงานส่วนนี้จะให้ผลการทำงานที่เร็วมาก

ทั้งนี้ เรายังสามารถ ส่งผลลัพธ์ สตริงโดยตรงไปให้กับ HtmlWriter ได้เนื่องจากวิธีนี้ จะมีความเร็วกว่าการเชื่อมต่อสตริงในแบบ
ที่เราใช้บ่อยๆ (string concatenaton)

วันศุกร์, กรกฎาคม 02, 2553

การสร้าง Proxy Class ผ่านคอมมานด์ไลน์

เราสามารถ สร้าง Proxy Class เพื่อให้เราเรียกใช้เว็บเซอร์วิสได้ โดยเมื่อเรา พัฒนาโปรแกรมตัวเว็บเซอร์วิสเรียบร้อยแล้ว
ให้คอมไพล์ โดย ทูล WSDL (Web Service Description Languague) ผ่านทาง บรรทัดรับคำสั่ง (Command Prompt) Wsdl /l:vb http://www.yourhost/WebService.asmx?WSDL
จะได้ซอร์สไฟล์เป็น WebService.vb ก่อนที่เราจะนำไฟล์คลาสไปใช้ จะต้องคอมไพล์อีกครั้งด้วย คอมมานด์ไลน์ ของ
Visual Basic ดังนี้
Vbc /t:library /r:System.dll,System.Web.Services.dll,System.XML.dll WebService.vb
จะได้ซอร์สไฟล์เป็น WebService.dll ให้ทำการ Copy ไฟล์ไปไว้ใน Sub-directory “bin” ของ Web Client ที่เรียกใช้
*** ข้อควรระวัง การคอมไพล์ด้วยทูล WSDL ให้กำหนดเป็น ชื่อเซอร์เวอร์ หรือ คอมพิวเตอร์เนม แทน Localhost ไม่เช่นนั้นเว็บเซอร์วิสจะใช้ได้ เฉพาะ Local Machine เท่านั้น

วันอังคาร, มิถุนายน 29, 2553

เมื่อใด(ไม่)ควรใช้ Web Services

เกณฑ์ในการพิจารณาใช้ Web Services

1. การส่งข้อมูลและสื่อสาร ผ่าน FireWall
2. Application Integration
3. Business to Business Integration
4. การนำ Software มา Reuse

เกณฑ์ในการพิจารณาไม่ควรใช้ Web Services

1. การใช้หลายๆ Applications บนเครื่องเดี่ยว
2. การใช้ Application ที่ต่างกัน บน LAN ในขณะที่มีทางเลือกอื่นดีกว่า ไม่ว่าจะเป็น .NET Remoting/DCOM

วันจันทร์, มิถุนายน 28, 2553

คอนโทรล ยืนยันตัวตน (Authentication)

การเปลี่ยนแปลงที่แสดงในคลาส Membership และคลาส Roles เริ่มมีให้เห็น ตั้งแต่ ASP.NET เวอร์ชั่น 2 ขึ้นไป ที่มา
พร้อมกับ คอนโทรลสำหรับ การยืนยันตัวตนต่างๆ ซึ่งช่วยให้เรา ทำงานกับข้อมูลผู้ใช้ และ เพจอีลีเม้นต์ ในแต่ละโพรไวเดอร์
ได้สะดวกง่ายดายขึ้น

คอนโทรล ด้านการตรวจสอบ อันดับแรกที่จะกล่าวถึง และมีประโยชน์มาก สำหรับใช้เพื่อการยืนยันตัวตน คือ คอนโทรล Login เป็นคอนโทรลที่ มีรูปแบบการผสมผสาน (composite) เพื่อนำชื่อผู้ใช้และรหัสผ่าน เข้าสู่ขั้นตอนการตรวจสอบสิทธิ และล็อกผู้ใช้เข้าระบบ หลักการทำงาน มันจะเรียกใช้ Membership.ValidateUser() และกรณี
ที่การป้อนข้อมูลของผู้ใช้ ตรงกับข้อมูลที่เก็บอยู่ในดาต้าสโตร์ ที่กำหนดโดย MembershipProvider แล้ว FormsAuthentication.SetAuthCookie() จะ ถูกเรียกขึ้นมาทำงาน จากนั้น ผู้ใช้ก็จะผ่านการล็อกอิน เข้ามาใช้งาน

คอนโทรลตัวถัดมาคือ LoginName ทำหน้าที่แสดงชื่อของผู้ใช้ที่ล็อกออนเข้ามาในขณะนั้น การแสดงผล ภายในเพจจะต้องกำหนดแทก ไว้ด้วย และมีพร๊อพเพอร์ตี้ FormatString ที่ช่วยให้เราจัดรูปแบบข้อความพิเศษได้ หากไม่มีผู้ใช้รายใดล็อกออนเข้ามา มันก็จะไม่แสดงอะไรขึ้นมา

สำหรับคอนโทรล LoginStatus มีลักษณะการทำงานเช่นเดียวกับคอนโทรล Login โดยมันจะแทรกแทก ไว้ในเพจ ในกรณีที่ผู้ใช้ไม่ได้ล็อกออนเข้ามา มันจะเตรียมลิงค์ให้กับเพจล็อกออน ที่ระบุแอททริบิ้ว loginUrl ไว้ในอีเลเม้นฟอร์ม จาก web.config เมื่อผู้ใช้ล็อกออนเข้ามา จะมองเห็น LinkButton แสดงแคปชั่น “Logout” ซึงจะเรียกใช้
FormsAuthentication.SignOut()และลบคุกกี้การยืนยันสิทธิของผู้ใช้ออกไป คอนโทรลนี้ยังประกอบด้วยพร๊อพเพอร์ตี้อีกมากมาย ซึ่งจะช่วยให้เราแก้ไขเปลี่ยนแปลงข้อความ และรูปแบบในแต่ละอีเลเม้นท์
คอนโทรล LoginView ใช้เท็มเพลตในการแสดงเนื้อหาที่สัมพันธ์กับสถานะหรือบทบาทของผู้ใช้ที่ล็อกออนเข้ามา วิธีนี้มีประโยชน์สำหรับการแสดงเฉพาะในส่วนเนื้อหา

วันศุกร์, มิถุนายน 25, 2553

Form Authentication


โหมด Forms ใช้เทคนิคการตรวจสอบสิทธิผ่านทางคุ๊กกี้ (cookie-based authentication) โดยที่เราไม่จำเป็นต้องสร้างรูปแบบ การตรวจสอบสิทธิผ่านคุ๊กกี๊ ด้วยตัวเอง เหมือนในอดีต เนื่องจาก ASP .net ดูแลและจัดการรายละเอียด ด้วยการ กระตุ้นให้เกิด กระบวนการ ให้ได้รับอนุญาติใช้งาน (authorization) ผ่านการยืนยันตัวตน การตรวจสอบสิทธิผ่านทางคุ๊กกี้ ดูขั้นตอนการทำงานประกอบ จากรูปภาพด้านบน

วันศุกร์, มิถุนายน 18, 2553

N-Tire Architecture


Layer หรือ Tier เป็นการวางการทำงานของระบบ แยกออกเป็นส่วน ๆ
โมเดลที่นักพัฒนานิยมนำมาใช้ ประกอบด้วย

1. Microsoft DNA Model แบ่งเป็น 3 Tier หลักๆ คือ Presentation, Business, Data access
2. Core J2EE Model แบ่งหลักๆได้ Client, Presentation, Business, Integration, Resource
3. Brown Model แบ่งได้ Presentation , Controller/Mediator ,Domain ,Data Mapping ,Data Source


การประยุกต์ใช้ ขึ้นอยู่กับขนาดของซอฟต์แวร์ ความเข้าใจของผู้พัฒนา ความเหมาะสมกับงาน “ไม่มีกฎตายตัว” แต่ ถ้าจะนำ Tier/Layer ใดมาใช้ ให้คำนึงถึง การเชื่อมต่อระหว่าง Layer และ วางกลไกลภายในให้ตรงกับลักษณะจุดประสงค์ของ Layer นั้นๆ โดยที่ อาจมีการยุบรวมเข้าด้วยกัน เช่น Façade(Controller) Layer + Application(Business) Logic Layer หรือ แตกย่อย Data Access Layer เป็น Layer อื่นๆ ได้อีก เพื่ออธิบายกระบวนการภายใน เช่น การรับข้อมูล การประมวลผล การจัดเก็บ/แสดงผล

วันพุธ, มิถุนายน 16, 2553

Role-Based Authentication

วิธีนี้ให้ประโยชน์ ในการสร้างเว็พแอพพลิเคชั่น ก็คือการกำหนด สิทธิ แบบ Role-Based Authentication ASP.NET สนับสนุน การยืนยันตัวตน แบบ Role-based โดยเรียกการทำงานของ เมทธอด IsInRole() ของ อินเตอร์เฟซ IPrincipal โดยอินทิเกรทการใช้เข้ากับ การยืนยันตัวตนผ่าน Windows ตัวเมทธอด IsInRole() จะทำหน้าที่ตรวจสอบ กลุ่มผู้ใช้สมาชิกบน Windows ในขณะที่ การยืนยันตัวตนผ่านคุกกี้ จะต้องใช้ role เพื่อการตรวจสอบความปลอดภัย เราจะต้องกำหนด role เหล่านั้น และสร้าง การจับกลุ่มเชื่อมโยง (Mapping) ระหว่างผู้ใช้ กับ roles นั้นๆ ด้วย วิธีที่สะดวก คือการเรียก คลาส GenericPrincipal ให้เรียกใช้เมทธอด IsInRole() ทำงาน โดยการตรวจเช็คชื่อดูว่าชื่อผู้ใช้ที่แอคทีฟอยู่นั้น สัมพันธ์หรืออยู่ใน roles ต่างๆ ที่กำหนดขึ้นหรือไม่



<%! File: global.asax %>
<%@ Import Namespace="System.Security" %>
<%@ Import Namespace="System.Security.Principal" %>

<%! File: global.asax %><%@ Import Namespace="System.Security" %><%@ Import Namespace="System.Security.Principal" %>

วันศุกร์, มิถุนายน 11, 2553

เทคนิคการ บันทึกเฉพาะส่วน (Save Points) ใน Transaction

เมื่อไหร่ ก็ตามที่เรา Rollback Transaction จะทำให้การปรับปรุงแก้ไข ทุกคำสั่งถูกยกเลิก และคืนสถานะเดิมของข้อมูลทั้งหมด โดยในบางครั้ง เราอาจไม่ต้องการ Rollback คำสั่งใด คำสั่งหนึ่ง จากทุกๆ คำสั่ง ก็เป็นได้ ฉะนั้นเราจำเป็นต้องหากลไก ที่จะ Rollback เพียงส่วนใดส่วนหนึ่งใน Transaction เราสามารถทำเช่นนั้นได้ ด้วยการใช้ SavePoints
SavePoints เป็นตัวทำเครื่องหมายที่ทำงานคล้ายกับ Bookmark เราอาจจะทำเครื่องหมาย ณ. จุดใด จดหนึ่งภายในการทำงานของ Transaction จากนั้นให้ Rollback กลับไปที่จุดที่ทำเครื่องหมายไว้ แทนที่จะ Rollback Transaction ทั้งหมด วิธีการคือ เราจะใช้ เมทธอด Save ในออบเจ็กต์ Transaction (ใช้ได้เฉพาะ คลาส SqlTransaction เท่านั้น)

ลิสติ่งที่ 1 พร้อมคำอธิบาย
Imports system
Imports System.Data
Imports System.Data.SqlClient

Module Module3

Sub Main()
Dim tConnection As SqlConnection
Dim tCommand As SqlCommand
Dim tTransaction As SqlTransaction
Dim tReader As SqlDataReader

‘ กำหนด ตัวแปรออบเจ็กต์ ต่างๆ เช่น Connection,Command และ Transaction เพื่อเชื่อมต่อไปยังฐานข้อมูล

Dim ConnectionString As String
ConnectionString = "Data Source=totsawat;Initial Catalog=Northwind;Integrated Security=True"
tConnection = New SqlConnection(ConnectionString)
tConnection.Open()

‘ เริ่มการทำงานของ Transaction โดยเรียกเมทธอด BeginTransaction ของออบเจ็กต์ Connection
tTransaction = tConnection.BeginTransaction()

tCommand = New SqlCommand()
tCommand.Connection = tConnection
tCommand.Transaction = tTransaction

Try
‘ เอ็กซิคิ้ว คำสั่ง SQL สเตทเม้นต์เพื่อการเพิ่มข้อมูล ทั้งหมด 5 ชุดคำสั่ง จาก ออบเจ็กต์ SqlCommand

tCommand.CommandText = "insert into orders default values"
tCommand.ExecuteNonQuery() ‘เรียกการทำงาน SavePoint ด้วยเมทธอด “Save” หลังจากเพิ่มเรคคอร์ดแรกแล้ว
tTransaction.Save("FirstOrder")
tCommand.CommandText = "insert into orders default values"
tCommand.ExecuteNonQuery()
tCommand.CommandText = "insert into orders default values"
tCommand.ExecuteNonQuery()
‘จากนั้น ให้ทำการเพิ่มเรคคอร์ดเข้าไปอีก 2 ชุดคำสั่ง แล้วเรียกเมทธอด rollback ย้อนกลับไปจนถึง จุด SavePoint ที่ชื่อ FirstOrder จะสังเกตเห็นว่า เราใช้ เมทธอด rollback พร้อมกับระบุชื่อของ SavePoint เป็นพารามิเตอร์ กรณีที่ต้องการ เรียกคืนสถานะเดิม (rollback) ทั้งหมดของ Transaction ไม่จำเป็นต้องระบุพารามิเตอร์
tTransaction.Rollback("FirstOrder")
‘ ต่อจากนั้น ให้ทำการเพิ่มเรคคอร์ดเข้าไปอีก 2 ชุดคำสั่ง และ สั่ง คอมมิท ตามปกติ
tCommand.CommandText = "insert into orders default values"
tCommand.ExecuteNonQuery()
tCommand.CommandText = "insert into orders default values"
tCommand.ExecuteNonQuery()
tTransaction.Commit()
‘ สุดท้ายให้เรียก หมายเลขออร์เดอร์ 3 รายการล่าสุด ขึ้นมาดู ทางหน้าจอ
tCommand.CommandText = "select top 3 orderid from " & _
"orders order by orderid desc "
tReader = tCommand.ExecuteReader()
Console.WriteLine("Last 3 Orders")

While tReader.Read()
Console.WriteLine(tReader.GetInt32(0))
End While

Catch e As Exception
Console.WriteLine(e.Message)
Console.ReadLine()
Finally
tConnection.Close()
End Try

End Sub

End Module

วันอาทิตย์, มิถุนายน 06, 2553

ทิป : ใช้หลักทางตรรกะที่ดีในการพัฒนาโปรแกรม

สภาพแวดล้อมตัวจัดการรันไทม์ของ .NET ได้เตรียม Garbage collection ขั้นสูงที่ออกแบบมาเพื่อปรับปรุงทรัพยากรที่ถูกใช้ไป และลบการอ้างอิงที่ไม่จำเป็นออกไป อย่างไรก็ตาม เราควรประยุกต์โครงสร้างตามกฏการทำความสะอาด เพื่อทำให้โค้ดอ่านง่ายและมีประสิทธิภาพ โดยเฉพาะอย่างยิ่ง ให้ยกเลิกการอ้างอิงออปเจ็กต์ที่ไม่ต้องการใช้งานแล้วทุกครั้ง กรณีที่เราใช้การเชื่อมต่อข้อมูล ต้องแน่ใจว่า เราได้เปิดการเชื่อมต่อในช่วงเวลาสั้นที่สุดเท่าที่เป็นไปได้ โดยจะเปิดการเชื่อมต่อ เฉพาะตอนที่จำเป็นจริงๆ และปิดการเชื่อมต่อ เมื่อไม่ต้องการ ใช้งานอีกต่อไป และไม่ควรปล่อยให้การเชื่อมต่อยังคงเปิดอยู่ภายในโค้ดโปรแกรมของเรา และโดยเฉพาะ ถ้าเรากำลังทำงานกับการสตรีมออปเจ็กต์ข้อมูล เช่น ออปเจ็กต์ DataReader

โดยสรุปแล้ว ให้ปิดการเชือมต่อและยกเลิกการอ้างไปยังออปเจ็กต์ที่ไม่ใช่แล้ว วิธีนี้เป็น หลักปฏิบัติของการโค้ดที่ดีและทำให้โค้ดมีความเหมาะสมและอ่านง่ายขึ้น

วันเสาร์, มิถุนายน 05, 2553

ทิป : การใช้ ตัวจัดการข้อผิดพลาด (Exception Handling) อย่างเหมาะสม

การใช้การจัดการ ความผิดพลาด (Exception Handler) มีข้อควรระวัง โดยเฉพาะอย่างยิ่ง การส่งข้อผิดพลาดต่างๆ ออกมาข้อแนะนำคือ ให้สร้างโครงสร้างเพื่อจัดการข้อผิดพลาด ขึ้นภายในแอพพลิเคชั่นของเรา แต่จะต้องออกแบบ ให้หลีกเลี่ยง การทำงาน ที่วิ่งเข้าไปภายในตัวจัดการข้อผิดพลาด เรื่องนี้สามารถเข้าใจได้ไม่ยาก ยกเว้นแต่เฉพาะนักพัฒนาผู้ใช้การ เขียนโค้ดขึ้นเอง อย่างเช่น การใช้ ASP รุ่นก่อน ใช้การเขียนโค้ดขึ้นเอง บ่อยครั้งมักใช้ การวางบล็อก คำสั่ง On Error Resume Next ที่ยินยอมให้โค้ด ประมวลผลคำสั่งอย่างต่อเนื่องผ่าน ค่าความผิดพลาด ไปแล้วค่อยมาตรวจสอบค่าผิดพลาดของผลลัพธ์ที่กำหนดไว้ในภายหลัง ซึ่งวิธีการนี้ ไม่ได้นำมาใช้ใน สภาพแวดล้อมการทำงานของ .NET ฉะนั้นควรออกแบบโค้ด ให้ใช้ตัวจัดการ ข้อผิดพลาด เป็นทางเลือกสุดท้าย โดยพิจารณา ค่าความผิดพลาดต่างๆ และตรวจสอบประเภทของฟังก์ชั่น เพื่อดักจับ ข้อผิดพลาดเหล่านั้น ก่อนที่จะทำการแปลคำสั่ง เท่ากับบังคับให้เรา แสดงข้อผิดพลาดในช่วงเวลาประมวลผล (runtime) ออกมา

การส่งข้อผิดพลาด เฉพาะกรณีที่จำเป็นจริงๆ เท่านั้น เนื่องจาก มันจะเป็นการทำงานที่สร้างภาระให้เรามาก (ในมุมมองการ ใช้ทรัพยากร การตรวจสอบโค้ดเพื่อแก้ไข ประสิทธิผลการทำงาน ฯลฯ) คลาส exception ได้จัดหา รายละเอียดต่างๆ มากมาย ที่ใช้ได้ โดยไม่ต้องใช้อาศัย การเรียกทำงานจากโค้ด ที่จะรับค่าที่ส่งข้อผิดพลาดออกมา ในกรณีนี้ จะเป็นการดีกว่า ที่จะแสดง ข้อผิดพลาดที่กำหนดขึ้นเอง โดยการใช้ Err.Raise แทนที่จะโยนไปให้ ตัดจัดการข้อผิดพลาด จัดการให้ การทำงานนี้ จะแปลงรายละเอียดข้อผิดพลาดพื้นฐาน อย่างเช่น หมายเลขข้อผิดพลาด แหล่งกำเนิด และข้อความ แต่มันจะหลีกเหลี่ยงรายละเอียดที่ซับซ้อน อย่างเช่น รายละเอียดของ Call stackท้ายนี้ ให้เราเตรียม ชุดคำสั่ง Catch หลายๆ ตัวพร้อมกับ รายการกรองเงื่อนไขต่างๆ จากนั้นจัดเรียงให้ ข้อกำหนดที่เกิดขึ้นบ่อยๆ เป็นค่าแรกที่โปแกรมจะตรวจพบ ดังแสดงตามตัวอย่าง

Try

Catch SqlErr as SqlException

Catch err As Exception

Finally

End Try

วันพฤหัสบดี, มิถุนายน 03, 2553

ทิป : ใช้การรวมกลุ่มการเชื่อมต่อ (Connection Pooling) ในการติดต่อฐานข้อมูล

ข้อพึ่งปฏิบัติในการเชื่อมต่อกับฐานข้อมูล คือ ควรเรียกใช้การรวมกลุ่มการเชื่อมต่อเป็นศูนย์กลางเสมอ เนื่องจากตัวจัดการเซิร์ฟเวอร์ SQL สนับสนุนการ รวมกลุ่มการเชื่อมต่อเป็นค่าเริ่มต้นอยู่แล้ว ทั้งยังสามารถลดภาระงานจากนักพัฒนาลงไปได้มาก งานส่วนมากที่เราจะต้องทำ ก็เพียงแต่แก้ไขรายละเอียดการเชื่อมต่อ เพื่อนำมาใช้แทนที่ค่าเริ่มต้นที่ตั้งไว้ ผ่านทางพารามิเตอร์การรวมกลุ่มการเชื่อมต่อ (Connection Pooling)

วันอังคาร, มิถุนายน 01, 2553

ทิป : การใช้ฟังก์ชั่นจากศูนย์กลางในการเรียกใช้ข้อมูล

ควรใช้วิธีเรียกข้อมูลจากส่วนกลางเสมอ ในไฟล์คลาสที่ออกแบบมาเฉพาะ วิธีดังกล่าวนี้ สามารถช่วยให้เราดูแลโค้ดฐานข้อมูล จากจุดกลาง เพียงแห่งเดียว ซึ่งทำให้ง่ายในการเขียนและแก้ไขปรับปรุง มันจะจัดทำฟังก์ชั่นอเนกประสงค์สำหรับวิธีเรียกใช้ข้อมูล ที่ประกอบด้วย

การประมวลคำสั่ง สโตร์โพรซีเยอร์และการคืนค่าผ่าน ออปเจ็กต์ DataReader
การประมวลคำสั่ง สโตร์โพรซีเยอร์และการคืนค่าผ่าน ออปเจ็กต์ DataSet
การประมวลคำสั่ง สโตร์โพรซีเยอร์และการคืนค่าผ่าน ออปเจ็กต์ XmlReader
การประมวลคำสั่ง สโตร์โพรซีเยอร์โดยไม่ส่งค่าคืน

ฟังก์ชั่นอเนกประสงค์ เหล่านี้ ปลอดจากการ กำหนดรายละเอียดของการ ตั้งค่าออปเจ็กต์การเชื่อมต่อ (Connection) และออปเจ็กต์ คำสั่ง (Command) เช่นเดียวกับ ในออปเจ็กต์ต่างๆ โค้ดที่มีอยู่เมื่อถูกนำมาใช้ซ้ำ และกำหนดค่า ตำแหน่งที่ตั้งต่างๆมากมาย นำมารวมไว้ภายในโค้ดของเรา วิธีดังกล่าวไม่เพียงยากที่จะปรับปรุงแก้ไข แต่มันยัง ทำให้ขนาดของแอพพลิเคชั่นที่จะประมวลผล ขยายตัวขึ้นไปอีกด้วย

วันพฤหัสบดี, พฤษภาคม 27, 2553

ทิป : ใช้สโตร์โพร์ซีเยอร์ที่ซับซ้อน ทดแทนการ เรียกอ่านข้อมูลหลายรอบ

ใช้สโตร์โพร์ซีเยอร์ที่ซับซ้อน สำหรับการแสดง ชุดผลลัพธ์ต่างๆ แทนที่จะเรียกอ่านข้อมูลหลายรอบ จากสโตร์โพรซีเยอร์หลายตัว ADO .NET นำเสนอวิธีที่ง่ายขึ้น ในการทำงานร่วมกับ ชุดผลลัพธ์ หลากหลายชุด อาทิ เช่น การใช้เมทธอด NextResult() ของ ออปเจ็กต์ SqlDataReader โค้ดดังกล่าวนี้ แสดงถึงวิธีการ สำรวจค่าทุกๆ เรคคอร์ด เพื่อแสดงผลชุดผลลัพธ์

sqlDR = objDB.RunQueryReturnDR("MyStoredProcedure")
Dim arrResult(0) As String
Do
While sqlDR.Read() ' การวางตำแหน่งตัวชี้ (pointer) ไปยังเรคคอร์ดแรกสุด
i += 1
ReDim Preserve arrResult(i)
arrResult(i) = sqlDR("ProductNumber")
End While
Loop While (sqlDR.NextResult())
' เลื่อนไปยัง ชุดผลลัพธ์ถัดไป

ถ้าจะให้ดี ให้เขียนสโตร์โพรซีเยอร์ เป็นแบทช์ ที่สัมพันธ์กับชุดผลลัพธ์ วิธีนี้จะช่วยใข้ลดการสัญจรบนเครือข่ายและ ช่วยลดภาระงานบน เซิรฟเวอร์ฐานข้อมูลได้

วันพุธ, พฤษภาคม 26, 2553

ทิป : ใช้ออปเจ็กต์การเข้าถึงข้อมูล (Data Access) ที่เหมาะกับงาน

  • งานด้านการเรียกดูข้อมูล ชนิดอ่านอย่างเดียว ให้ใช้การสตรีม เพื่อการเข้าถึงข้อมูล
  • ใช้ออปเจ็กต์ DataSet สำหรับงานปรัปบรุงข้อมูล กรณีที่เราต้องการ ทำการปรับปรุงแบบไร้การเชื่อมต่อ (อีกทางเลือกหนึ่ง สามารถ สร้าง สโตร์โพรซีเยอร์เฉพาะ เพื่อจัดการ ด้านการปรับปรุงข้อมูล)
  • ใช้ ออปเจ็กต์ DataView เมื่อเราต้องการทำงานกับ มุมมองแบบกรองรายการ ของออปเจ็กต์ DataSet ขนาดใหญ่ เพราะออปเจ็กต์นี้ ได้จัดเตรียม คุณลักษณะ ที่มีประโยชน์มากมายของ ออปเจ็กต์ DataSet ขณะเดียวกัน มันก็ใช้งาน ทรัพยากรระบบน้อยกว่า การใช้ออปเจ็กต์ DataSet โดยตรง

วันอาทิตย์, พฤษภาคม 23, 2553

ควรใช้ Transaction เมื่อไหร่

การนำ Transaction มาใช้ จะทำให้เกิด Overhead ในการทำงานของระบบ และมีผลโดยตรงกับ Performance ดังนั้น นักพัฒนา จะต้องพิจารณาให้ครอบคลุม ผลกระทบดังกล่าว ถึงแม้ว่า ADO .net จะสนับสนุนการทำ Transaction ได้ค่อนข้างดีก็ตาม ให้อาศัยหลักเกณฑ์ในการพิจารณาว่า จะใช้ Transaction เมื่อ โพรเซสของงาน ต้องอาศัย การประมวลผลในหลายส่วนงาน (มีโพรเซสงานเข้ามาเกี่ยวข้องมากว่า 1 รายการ) เพื่อให้ผลลัพท์ของข้อมูลที่เกี่ยวเนื่องกันมีความถูกต้อง

วันเสาร์, พฤษภาคม 22, 2553

ค่าที่กำหนดให้ Isolation Level มีดังนี้

Chaos การแก้ไขที่คงสถานะ “รอ” Pending โดยกำหนดค่าระดับที่ ไม่อนุญาตให้เขียนทับ
ค่าได้ จนกว่า การทำงานของ Transaction จะสิ้นสุด (SQL Server ไม่รองรับข้อ
กำหนดนี้ )

ReadUnCommitted เหมือนข้อกำหนด Dirty Read : ไม่มีการทำ Shared Lock และการกำหนด
Exclusive Lock Isolation ชนิดนี้ เหมาะสำหรับ การทำงาน กับทุกข้อมูลที่ตรง
กับ เงื่อนไข โดยไม่สนใจว่า Transaction จะ Commit หรือไม่

ReadCommitted ขณะที่อ่านข้อมูล จะกำหนด Share Lock ไปยังชุดข้อมูล ที่ Transaction ทำ
งานอยู่ เพื่อหลีกเลี่ยงการอ่านข้อมูล แบบ Dirty Read ผลลัพท์จะเหมือนกับ
Non-Repeatable Read หรือ Phantom Rows Isolation ชนิดนี้ เหมาะสำหรับ
การทำงาน กับทุกข้อมูลที่ตรงกับ เงื่อนไข และ Commit แล้วเท่านั้น และค่านี้ยัง
เป็น ค่าดีฟอลท์ สำหรับ Isolation Level หากไม่ระบุใน Transaction

RepeatableRead กำหนด Share Lock กับข้อมูลทั้งหมดที่ใช้ในคิวรี เพื่อป้องกันการแก้ไขข้อมูลจาก
ผู้ใช้คนอื่นๆ และ ป้องกันการอ่านแบบ Non-Repeatable Isolation ชนิดนี้ เหมาะ
สำหรับ กรณีที่เราต้องการ รายการข้อมูล (Record) ที่อ่านเข้ามา ยังคงเป็นค่า
เดิมในการอ่านข้อมูลครั้งต่อไป

ResizeableRead กรณีนี้ จะล็อก ชุดข้อมูล เพื่อป้องกันการแก้ไขและเพิ่มข้อมูลจากผู้ใช้คนอื่นๆ จน
กว่า Transaction จะทำงานเสร็จ Isolation ชนิดนี้ เหมาะสำหรับ กรณีที่เราต้อง
การ ชุดข้อมูลที่เราทำงานอยู่ เป็นชุดข้อมูลเดียวกัน จนกระทั่งเราประมวลผล
รายการจนแล้วเสร็จ

UnSpecified กรณีนี้ คือการนำ Isolation Level ที่ต่างจากข้อกำหนดมาใช้ ซึ่งไม่สามารถระบุ
Isolation Level ได้

วันศุกร์, พฤษภาคม 21, 2553

ข้อกำหนดทั่วไปสำหรับ Isolation Level

ข้อกำหนดทั่วไปสำหรับ Isolation Level Dirty Read = คือข้อกำหนด ที่ Transaction หนึ่งสามารถอ่านข้อมูลได้ ในขณะที่ Transaction อื่นๆ กำลังแก้ไขข้อมูลอยู่
Non-Repeatable Read = การแก้ไขใน Transaction หนึ่ง มีผล ทำให้การเรียกดู ข้อมูลเปลี่ยนแปลง ตัวอย่างเช่น Transaction A เรียกดูข้อมูลมาดูชุดแรก ระหว่างนั้น Transaction B ทำการอัพเดตข้อมูล จากนั้น Transaction A เรียกดูข้อมูลชุดถัดมา ผลลัพท์ ที่ได้ จะต่างจากครั้งแรก แม้จะใช้ ชุดคำสั่งเดียวกัน
Phantom Read = กรณี Transaction A วางเงื่อนไข สำหรับ เรคคอร์ดที่เลือก เมื่อ Transcation A ต้องการแสดง 100 รายการที่ตรงตามเงื่อนไข ในระหว่างนั้น Transaction B แทรกข้อมูลบางรายการ เข้าไปตรงกับเงื่อนไขที่กำหนดใน Transaction A จะมีผลให้ เมื่อ Transaction A คิวรีข้อมูลอีกครั้งจะได้ ผลลัพท์ที่ต่างไปจากเดิม เราเรียก การเพิ่มรายการโดยวิธีนี้ว่า Phantom Rows

วันพฤหัสบดี, พฤษภาคม 20, 2553

พร๊อพเพอร์ตี้ ACID ?

การที่จะนำ Transaction มาใช้ ต้องพิจารณาถึง คุณลักษณะของ ACID อันประกอบไปด้วย
Atomic = ในทุกขั้นตอนของ Transaction ควรจะประกอบไปด้วย จุดที่แสดงถึง “ความสำเร็จ” และ “ความผิดพลาด”
Consistent = Transaction สามารถทำให้ข้อมูล เปลี่ยนจาก สถานะเดิม ไปเป็น อีกสถานะหนึ่ง
Isolated = ในแต่ละ Transaction จะมีอิสระต่อกัน โดย Transaction ใดๆ ไม่อาจแทรกแซงขณะที่ Transaction หนึ่ง กำลังทำงานอยู่
Durable = การเปลี่ยนแปลงที่เกิดขึ้นจาก Transaction จะถูกเก็บบันทึกไว้ใน สื่อบันทึกข้อมูล ก่อนที่ Transaction จะประมวลคำสั่ง เป็นผล “สำเร็จ” Log การเปลี่ยนแปลงจะถูกบันทึกไว้ ดังนั้นถ้าเกิด “ความผิดพลาด” ขึ้น ชุดข้อมูลใน สื่อบันทึก จะต้องสามารถ ฟื้นคืนสถานะ (Reconstruct) กลับมาได้