Nine นาย's profile<[Nine]> My BLOG ^ ^BlogLists Tools Help

<[Nine]> My BLOG ^ ^

เพิ่มเติมไปเรื่อย ๆ กับความรู้... (distributed knowledge component)
July 01

[Article] Pattern Series : Understand the ASP.NET MVC (Draft version)

Agenda

  • Pattern Series : Understand the ASP.NET MVC
  • Pattern Series : ASP.NET MVC

Programmer Level

Intermediate / Advance

Introduce

จะว่าไปแล้วเรากำลังศึกษาระบบโบราณอยู่ครับ MVC นั้นเป็นทั้ง Arichitectural Pattern และ Design Pattern ที่มีมานานมากสมัยปี คศ. 1979 โดยนาย Trygve Reenskaug พัฒนาตัวนี้ให้ smalltalks บน PARC   ซึ่งเท่าที่ผมศึกษาดูมาคร่าว ๆ ใน platform อื่น ๆ แทบทุกภาษาจะมี MVC Framework ไว้ให้ใช้    ฝั่ง Java คงไม่ต้องกล่าวถึงเพราะเป็นเจ้าแห่งการ implement pattern เกือบทั้งหมดที่มีอยู่ในโลกบวกกับที่คิดค้นใหม่และเติบโตขึ้น    ส่วนฝั่ง .NET เองก็พัฒนาต่อยอดมาเป็น MVP(พัฒนาพวกผม,,, ไม่ใช่! ไว้จะอธิบายตอนหลัง)   แม้กระทั้งภาษาอย่าง PHP ที่เป็น scriptlet ก็ยังมี MVC ให้ใช้กัน โอ้โฮ.. แบบนี้ MVC มันดียังไง แล้วทำไมทุก Platform ต้องมีเจ้านี่ไว้ในระบบบทความเรื่องนี้เราจะมาคุยกันครับ

จากที่มา หลาย ๆ คนคุ้นเคยกันดี กับ wizard ของ Visual Studio หรือ Dev Tool ตัวที่ทำงานในลักษณะคล้าย ๆ กัน เมื่อกด double click ที่ control ต่าง ๆ แล้วจะสร้าง Event Click ให้ใน Codebehind     สิ่งนี้นำพาโปรแกรมเมอร์ทั้งหลายไปทำงานในลักษณะของ Event Programming (แบบบ้าน ๆ ) หลังจากได้ Click Event แล้ว งานอะไร คิดอะไรได้ก็โค้ด ๆ เขียนใส่ลงไปทั้งหมด จะประกาศตัวแปร, จะติดต่อ Database, จะเรียก web service, จะวนลูปสามล้านรอบ ทุกอย่างประดังลงไปใน Event Click   ดีหน่อยบางคนใส่ try catch ให้ด้วยดัก Errror

สิ่งที่ทำนี้โค้ดทั้งหมดจะไปฝังอยู่ใน class/module เดียวกัน ทำให้ชุดของโค้ดนั้นปนกันระหว่าง presentation logic, business logic     หากจะถามว่าผิดหรือไม่ ตอบว่าไม่ผิดในเชิง production เพราะตอบโจทย์ business, งานสำเร็จ และคุณรอดตัวไปได้ในวันนี้  แต่เมื่่อวันนึงคุณต้องแก้เพียงแค่ filter ค่าบางตัวออกจากการ input, คุณแค่ต้องการเปลียนสี ข้อความบนหน้าจอโปรแกรม

What’s The MVC Pattern

จะว่าไปก็หาอ่านได้ตาม Blogs โดยทั่วไปนะครับ ทุกท่านเขียนไว้ค่อนข้างดีและใช้อ้างอิงได้ แต่ผมขอเขียนด้วยละกันเอ้า!!

 

MVC เป็นตัวย่อมาจาก Model / View / Control ซึ่ง Pattern ตัวนี้ต้องการจะแยก 3 สิ่งนี้ออกจากกัน มองแลไปก็คล้าย Layer ที่มี association ระหว่างกัน แต่ทั้งสามก็ทำงานอยู่ภายใน Presentation Layer เพราะ MVC สร้างมาเพื่อจัดการกับ Presentation Layer โดยเฉพาะครับ

ASP.NET Series : Membership Provider extend with NHibernate

จะเขียนแล้ว ๆ ๆ ๆๆ ๆ ๆ  กำลังทดสอบ Coding อยู่ หึหึหึ นานหน่อย….

June 30

ORM Series : Start to ORM World (Draft version)

Agenda:

  1. ORM Series : Start to ORM World
  2. ORM Series : NHibernate

Introduce

ห่างหายไปนานครับ กับการเขียนบทความลง GF นี่เรียกว่ากลับมาในรอบปีเลยก็ว่าได้ ส่วนใหญ่จะไปเน้นงาน Offline Meeting เสียมากกว่า เรามาเข้าเรื่องกัน

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

พวกเราเป็นนักพัฒนาโดยใช้เทคโนโลยีของไมโครซอฟต์ เริ่มต้นที่ผมได้รู้จัก Library ที่ไว้ใช้เข้าถึง Database มีทั้ง DAO, RDO และ ADO ซึ่งตอนนั้นก็ยุคของ Microsoft Access และ VB6 กำลังรุ่งเรืองเลยก็ว่าได้ โดยการทำงานจะมุ่งเน้นไปที่ Database, Table, Row, Column, StoreProcedure และ Function สนใจเพียงลักษณะของโครงสร้าง column ที่จะดึงมาแสดงผลข้อมูล การคำนวนค่าใน database และส่งกลับมายังโปรแกรมเพื่อทำงานใด ๆ ต่อไป

ms978510.f01daag02(en-us,MSDN.10).gif

Figure 1. Currently Microsoft Data Access Component (msdn reference)

ต่อมายุคคือยุคของ ADO.NET ซึ่งย้ายมาทำงานบน .NET Framework เป็นการเพิ่มความสามารถของ ADO โดยเสนอ Dataset Class โดยทำงานในลักษณะของ multi table, relation และอื่น ๆ อีกมากมาย ในตอนนั้นเรียกว่าฮือฮากันเลยทีเดียว เกิดการเปลี่ยนแปลงการเขียนโปรแกรมกันพอสมควร (รวมผมด้วย) ซึ่ง Dataset จะมีทั้ง Untyped และ Typed ให้เลือกใช้งานกัน จนทุกวันนี้ก็ยังมีใช้งานกันแพร่หลาย อีกทั้งมี library ตัวใหม่ๆ อย่าง TableAdapter เป็นต้น ปัจจุบันนี้ Dataset มีใช้งานทั่วไปทั้งในระบบงานเล็ก ๆ ไปจนถึงระบบงานขนาดใหญ่ก็ยังคงพบเห็น เพราะว่ามีความรวดเร็วในการพัฒนา มีความยืดหยุ่นสูงในการทำงานของ code และยังสามารถ serialize ตัวเองไปเป็น xml เพื่อส่งผ่านไปทาง Web Service Technology ซึ่งหลังจากที่ใช้งานมาตลอดยุคหนึ่ง จนมาถึงปัจจุบันในความเห็นส่วนตัว ผมมองว่า Dataset เหมาะสมกับงานที่มุ่งเน้นไปที่การออกแบบระบบทาง Functionality + Data เพราะมองเห็นไปถึง Database Schemay โดยถูกกำหนดการทำงานโดย Business Functionality สิ่งนี้เองที่ทำให้ Dataset ยังคงอยู่จนทุกวันนี้ และจะยังคงอยู่ต่อไปอีกนาน เพราะว่าบุคลากรนักพัฒนาส่วนใหญ่ยังคงใช้ Functionality Design and Programming หรือเรียกได้อีกแบบว่า Data Driven Programming (ตัวอย่าง.. หลังได้ ERD, User Screen, Requirement แล้วลุยพัฒนาเลย)

.NET Framework เป็น framework ที่พัฒนาขึ้นให้ภาษาต่าง ๆ ที่ต้องการจะเข้ากับ framework นั้นต้องตรงตามมาตรฐานที่กำหนดไว้ และกันนี้เองทำให้ภาษาเหล่านั้นต้อง support Object Oriented ไปด้วยโดยปริยาย และด้วยความสามารถนี้ทำให้การ port library, framework ต่าง ๆ จากกลุ่ม OO Language อย่าง JAVA มีความนั้นเป็นไปได้สูง และนี่ก็เป็นจุดเปลี่ยนของ Microsoft Technology เหล่านักพัฒนาเริ่มทะยอยหันกันมาศึกษาและแลกเปลี่ยนความรู้ของ .NET Framework กันแพร่หลาย จนกระทั่งได้มีการนำ open source จาก Java หลาย ๆ ตัวย้ายลงมาพัฒนาบน .NET Framework ให้เราได้เห็นกันจนทุกวันนี้ ไม่ว่าจะเป็น Unit Testing Framework, Logging Framework, MVC Framework, DI และ Object Relational Mapping Framework ก็คือที่เราจะมาคุยกัน

ที่มาของ ORM โลกปัจจุบันเราก็ทราบกันดีว่า Object Oriented Analysis Design and Programming นั้น ช่วยให้เราพัฒนาระบบงานให้มีความใกล้เคียงกับโลกในชีวิตจริง ข้อดีต่าง ๆ ทางด้านการพัฒนาระบบ การดูแลรักษา การพัฒนาต่อยอด ล้วนแล้วแต่เหนือกว่าการพัฒนาแบบ Functionality Style ค่อนข้างมาก แต่ด้วย Database Technology ในปัจจุบันนี้ RDBMS นั้นเป็นที่นิยมใช้งานในปัจจุบันและแพร่หลาย แถมยังมีทีท่าว่าจะรุ่งเรืองต่อไปอีกนาน นี่ก็เป็นปัญหาของการพัฒนาระบบงานแบบ Object Oriented อย่างมาก เนื่องจากคอนเซ็ปการทำงานนั้นแตกต่างกัน จึงกลายเป็นที่มาของ ORM

What’s Object Relational Mapping

ลักษณะของ Business Object จะมีความหลากหลายของโครงสร้าง ตลอดจนลักษณะความสัมพันธ์ระหว่างอ็อปเจ็คก็มีความซับซ้อนทั้งแบบ Hierarchy, Composite และ Association ซึ่งแตกต่างจาก Table Relation ในดาต้าเบสมาก ทำให้ผู้พัฒนาต้องเกิดปัญหาในการจัดการเก็บข้อมูลลง RDBMS

[BillingSystemDatabaseModel.jpg]    [BillingSystemClassDiagram.jpg]

Figure 2. Table Relation Model

Figure 3. Object Relation Model

จากรูปด้านบน จะเป็นการเปรียบเทียบระหว่าง Table Relation กับ Object Relation  จะพบว่ามีลักษณะใกล้เคียง แต่ใน real world นั้นบางครั้ง Object Relation อาจจะมีความซับซ้อนกว่านี้เช่น  Register Customer Class และ Non Register Customer Class ได้ inheritance Customer Class ไป และการเข้าถึง Object อื่น ๆ ที่เกี่ยวข้องกันจาก Diagram เดิมนั้นจะเปลี่ยนไป เช่น Register Customer Class สามารถวางบิลได้ แต่ Non Register Customer Class จะไม่สามารถวางบิลได้ เพราะเงื่อนไขว่า Non Register Customer ไม่สามารถ Order สินค้าได้เป็นต้น

ความซับซ้อนของ Business Object ที่ได้กล่าวไปข้างต้นนั้นเป็นจุดที่สร้างปัญหาในการเก็บข้อมูลลง Table ใน Database เป็นอย่างมาก จนได้เกิดหลักการ Map Object เข้ากับ Table ใน Database ออกมาเป็นหลาย Pattern ซึ่งจะเป็นลักษณะของ Best Practice แต่ไม่ใช่ Standard  และจาก Pattern ต่าง ๆ เหล่านี้ก็ไม่ได้ช่วยลดปัญหาในการพัฒนาตัว ORM Library ให้กับชาว OOP ลงเท่าไหร่ เพราะต้องเสียเวลาในการพัฒนา DAL ที่ทำหน้าที่เป็น ORM อีกชั้นนึง คอยไปดึง Column จาก Table ต่าง ๆ มาสร้างเป็น Object ในระบบ และต้องนำ Property ของ Object ในระบบไป insert ลงยัง Column ใน Table ต่าง ๆ และระดับของ Object ที่มี Ralation กันลึก ๆ หลายระดับ แค่นี้ก็แสบสมองแล้วครับ 

หลายคนก็พยายามเขียน DAL Method ขึ้นเองเพื่อใช้ตอบสนอง Business Method ที่ต้องการใช้งาน Object แต่จากที่กล่าวไว้เบื้องต้นด้านบน นอกจะจะเสียเวลาในการพัฒนาแล้ว ยังเสี่ยงต่อ Bug ที่จะเกิดขึ้นในอนาคต และดูแล้วยากต่อการแก้ไขเปลี่ยนแปลงในตอนหลังด้วย  แต่ไม่ต้องกังวลครับ ปัญหาเหล่านี้ได้มีนักพัฒนาแก้ปัญหาให้ท่านแล้ว ซึ่งมีผู้พัฒนา ORM Framework ออกมาหลายรายทั้งในรูป Open Source และ Commercial แต่จะใช้พูดถึงในบทความ จะขอยกตัวอย่างแค่ ADO.NET Entity Framework และ NHibernate เท่านั้น เพื่อไม่ให้เกิดความสับสนในการศึกษาครับ (จริง ๆ ตัวเดียวก็ปวดหัวแล้ว)

เกรงว่าหากบรรยายไปจะยืดเยื้อ อ่านต่อเกี่ยวกับ ORM ที่นี่ http://www.agiledata.org/essays/mappingObjects.html อ่านจบแล้วจะเข้าใจโลกของ ORM ขึ้นอีกครับ

Object Relational Mapping Framework

ORM Framework จะช่วยลดงานพัฒนาส่วนของการติดต่อกับ Database ให้ครับ โดยคุณจะสามารถ Find/Add/Update/Delete Object ผ่านลงไปยัง Database ได้โดยไม่ต้องเขียน Code จัดการเอง รวมไปถึงข้อดีต่าง ๆ จาก ORM Framework แต่ละตัวเช่น Caching, Validation, etc. ซึ่ง Functionality ที่ ORM Framework จะต้องมีและควรจะมีนั้นมีประมาณนี้ครับ

    • รองรับการทำ Inheritance ระหว่าง Entities, และจะต้องเรียกใช้งานในลักษณะของ Polymorphism
    • สามารถรองรับ relations แบบ 1-1, 1-n, n-n
    • รองรับการทำ transactions
    • Aggregates สำหรับ จัดการดึง object (equivalent to SQL's SUM, AVG, MIN, MAX, COUNT)
    • รองรับการทำ grouping (SQL's GROUP BY)
    • Support Database อย่างน้อย 1 ชนิด (เอ… งง)
    • มี OQL, OPath ใช้ในการดึง object
    • รองรับการทำ Databinding (ส่วนใหญ่ IList ก็เป็น standard ของ .NET Data Control แล้ว)
    • ทำ Join (inner, outer)
    • Concurrency Management
    • Database specify type พวก column type แปลก ๆ อย่าง uniqueidentify, sequence ประมาณนั้น
    • สามารถ Map 1 object มาจากหลาย ๆ Table ได้
    • สามารถดึงข้อมุลจาก Table เดียวไปเป็น หลาย ๆ object ได้
    • ควรจะมี GUI ช่วยในการทำ Mapping
    • ควรจะมี Code Gen
    • ควรจะสร้าง Table Schema ได้จาก MAP
    • ระบบควรจะมีประสิทธิภาพในการทำงานสูงโดยรวม
    • สามารถทำ Lazy Loading Object ได้
    • สามารถสร้าง dynamic sql จาก code ได้เอง
    • มี Cache สำหรับ Data ที่จำเป็น
    • สามารถ optimized queries ให้เหมาะสมได้
    • จัดการลักษณะ Circular References
    • ทำ Cascade updates. Bulk updates or deletions
    • …. อีกมากมาย

สาเหตุที่ต้องทำให้คุณควรจะเลือกใช้ ORM Framework ที่มีอยู่แล้วในปัจจุบัน นั้นมีดังนี้

  1. ORM ช่วยลดเวลาในการพัฒนางานของคุณลง 20-50% รวมกรณีต่าง ๆ ในระบบเล็ก ๆ ที่มีประมาณ 10 tables ใน Database และมี Domain Object ราว ๆ 20 objects คุณต้องเขียนโค้ดในการจัดการหลายหมื่นบรรทัด แต่ถ้าคุณใช้ ORM คุณจะใช้เวลาเพียงแค่ไม่เกิน 2 วันครับ
  2. ORM ส่วนใหญ่ที่มีมักเป็น Better of Design และ Code Quality ยิ่งตัวที่มีอายุการพัฒนายาวนาน มี community และมี developer ใช้งานเยอะ ๆ แล้ว ล้วนแต่ไว้วางใจได้ครับ 
  3. ลดคนที่ต้องมาพัฒนาส่วนจัดการ Database
  4. ORM ช่วยลดเวลาในการทำ Test แน่นอนหละครับ มี Community มี User นำไปใช้งานจริง มี bug/issue อะไรก็แจ้งให้แก้ไข ยิ่งพวก Commercial ด้วยแล้ว QC เชื่อถือได้แน่นอนครับ
  5. ORM ช่วยให้คุณลดความยุ่งยากในการเรียนรู้และการทำงานกับ Database ให้เหลือเพียง คุณจะ Get/Update/Add/Delete object ยังไงเท่านั้น

เป็นไงครับ ฟังแล้วพอจะรู้ทางเลือกแล้วใช่มั้ยครับ ว่าเราจะเลือกพัฒนา Custom ORM เองหรือจะใช้ ORM Framework ที่มีอยู่มากมายในปัจจุบัน ผมมีรายชื่อ ORM มาฝากครับ

Name

Open Source

Commercial

Current Version

Multiple Database

LINQ support
ADO.NET Entity Framework - Microsoft 1.0 Yes / with 3rd Party Yes
LINQ To SQL - Microsoft 1.0 SP1 MSSQL only Yes
NHibernate
(port from Hibernate JAVA)
Fabio Maulo - 2.0.1 GA Yes with LINQ to NH
Castle Active Record Castle Project - 2.0 Alpha 1 Yes N/A
SubSonic Rob Conery - 2.2 Yes Yes
LLBLGen Pro - LLBLGen 2.6 Yes Yes
Genome - Genome 4.1 Yes Yes
           
Table 1. ORM tool List

ซึ่งบทความนี้ผมจะขอพูดถึง ORM 2 ตัวคือ NHibernate และ ADO.NET Entity Framework ครับ ซึ่งในตอนหน้าจะลงรายละเอียดของ NHibernate

เจอกันตอนหน้าเร็ว ๆ นี้ สวัสดีครับ

 

Nine (นาย)

GF Community Lead

Microsoft MVP Thailand

March 04

Article: มาสร้าง Windows Service ใช้กันดีกว่า (ตอนที่ 1)

Article: มาสร้าง Windows Service ใช้กันดีกว่า (ตอนที่ 1)

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

 

What article covering?

  • แนะนำความรู้พื้นฐานเพื่อทำความเข้าใจเกี่ยวกับ Windows Service
  • สร้าง Windows Service Project โดยใช้ตัวอย่างงานจริง
  • Deployment (MSI Package, MSBuild ตอนที่2)
  • Debug Windows Service (ตอนที่2)

 

What’s a Windows Service?

คือ Program ที่สร้างและ deploy ไปแล้ว จะทำงานเป็น Service รันอยู่บน Windows โดยสามารถที่จะตั้งค่าให้ run program ไปพร้อม ๆ กับ Windows start up ได้ โดยทำงานเป็น Background Service โดยที่ user ไม่ต้องสั่งงานใด ๆ

โดยการทำงานนั้นอาจจะเป็นในลักษณะของการทำงานตามช่วงเวลา, การทำงานตาม event ที่ต้องการ เช่น การทำงานร่วมกับ FileSystemWatcher หรือ System.Timers.Timer เพื่อใช้ Event ที่เกิดขึ้นเป็น Trigger ในการทำงานบางอย่างตามเงื่อนไขที่ต้องการ                 

Mention the Windows service.

            เนื่องจากประโยชน์ของ Widows Service หลัก ๆ ก็คือ Program ที่เราสร้างนั้นสามารถที่จะทำงานได้โดย automatic ทันทีที่ Windows ได้ Start up และการทำงานของโปรแกรมนั้นจะเป็นในลักษณะของ Background Service คือจะทำงานตามที่เราได้ตั้งเงื่อนไขการทำงานไว้ หลังจาก Service Start แล้ว และ Windows Service นั้นจะสามารถเลือก User เพื่อที่จะให้สิทธิ์สั่งการทำงานของ service นั้นได้ (ค่า default ส่วนใหญ่จะใช้ LocalService, NetworkService User)  หากเพื่อน ๆ เคยเปิดดูใน Administrative Tools -> Services จะเห็น Windows Service จำนวนมากดังรูปข้างล่างนี้

 

    ซึ่งโปรแกรมส่วนใหญ่ทั้ง MSSQL, ASP.NET, IIS, etc. ต่างก็มีการใช้ Windows Service เป็นตัวคอยควบคุมการทำงานของระบบตามที่ได้วางเงื่อนไขการทำงานต่าง ๆ ของระบบไว้ในตัว service ทำให้เสมือนโปรแกรมนั้นมีชีวิต สามารถทำงานได้ด้วยตัวเองอยู่บน Windows แต่เป็นไปตามเงื่อนไขที่เราได้กำหนดการทำงานไว้

 

Create my first Windows Service.

 

Create Solution and Windows Service Project

เริ่มแรกเลือกสร้างโปรเจ็คแบบ Windows Service ตามรูปข้างล่าง

 

จากนั้นก็จะได้โครงสร้างโปรเจ็คในหน้าต่าง Solution Explorer ตามรูปข้างล่างนี้

 

ซึ่ง Service1.cs จะเป็น file ที่เราจะทำการ coding ลงไปเพื่อควบคุมการทำงานตามที่เราต้องการ

เมื่อเราเปิดกดเลือกดู   View code icon เราจะเห็น code ตาม list ข้างล่างนี้  

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Diagnostics;

using System.ServiceProcess;

using System.Text;

 

namespace myService

{

    public partial class Service1 : ServiceBase

    {

        public Service1()

        {

            InitializeComponent();

        }

 

        protected override void OnStart(string[] args)

        {

            // TODO: Add code here to start your service.

        }

 

        protected override void OnStop()

        {

            // TODO: Add code here to perform any tear-down necessary to stop your service.

        }

    }

}

 

จะพบได้ว่ามี 2 methods ที่ได้ override จาก base class คือ OnStart() และ OnStop() ซึ่งจะเป็น Event default ที่ถูกสร้างมาให้ และจะเกิด Event เหล่านี้ขึ้นตามสถานะการทำงานของ service นั้น ๆ ซึ่งผมได้สรุปมาเท่าที่เราจะใช้กันบ่อย ๆ ได้ดังนี้

 

Event Name

 Description

OnStart()

จะเกิด event นี้เมื่อ service ถูกสั่งให้ start ซึ่งเรานิยมใช้ในการสั่งการให้ตัวTrigger (Timer, FileSystemWatcher, Thread) ที่เราใช้ใน Service นั้นทำงาน

OnStop()

จะเกิด event นี้เมื่อ service ถูกสั่งให้สั่งให้ (stop) นิยมใช้ในการ save states ต่าง ๆ ของ Service ที่จำเป็นไว้

OnPause()

จะเกิด event นี้เมื่อ service ถูกสั่งให้สั่งให้ค้างการทำงาน (pause)

OnContinue()

จะเกิด event นี้เมื่อ service ถูกสั่งให้สั่งให้ทำงานต่อ (resume)

OnShutdown()

จะเกิด event นี้เมื่อ windows ถูกสั่งให้ restart / shutdown

 

Implement Functionality

            ต่อไปจะทำการใช้ Windows Service ในการทำ Backup file จาก Drop File Folder ย้ายไปเก็บยัง Backup File Folder ซึ่งจะมีการเพิ่มการทำงานดังนี้

 

  1. คอยตรวจสอบหากมีการ create/ paste file ลงใน drop file folder ให้ raise event
  2. ให้เก็บ full path ของ file ที่ notify เก็บไว้ใน collection ก่อนนำไป process ต่อไป
  3. ใช้ Timer ในการ process file list ใน collection ในแต่ละรอบเวลา โดยกำหนดจำนวน file ในแต่ละรอบได้ เพื่อเพิ่มประสิทธิภาพในการทำงานให้เสถียรขึ้น
  4. ให้ทำการ move file โดยอ่าน path จาก collection ไปยัง Backup Folder
  5. หากทำการ move file สำเร็จให้ลบ file path นั้นใน collection ทิ้งไป
  6. เก็บ service status(start, stop) , Application Error ไว้ใน Event Log

 

เราก็จะสร้าง file ขึ้นมา 3 files ดังนี้ 

  1. เพิ่ม App.config เข้ามาเพื่อใช้ในการตั้งค่าการทำงานต่าง ๆ ของ windows service โดยทำการคลิ๊กขวาที่ project -> Add -> New Item... -> Application Configuration File จากนั้น เพิ่มค่า config เข้าไปตามตารางข้างล่างนี้

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

      <appSettings>

            <!-- ServiceMode you can config for Copy=0, Remove=1, Delete=2 -->

            <add key="ServiceMode" value="0"/>

            <!-- FileFilter = file mask such as *.txt, *.jpg, *.* -->

            <add key="FileFilter" value="*.*"/>

            <!-- FileMonitoringPath = -->

            <add key="FileMonitoringPath" value="c:\test\master"/>

            <!-- ServiceTimer = Time for service process job in Second -->

            <add key="ServiceTimer" value="3"/>

            <!-- TargetFolder use to copy or move file-->

            <add key="TargetFolder" value="c:\test\backup"/>

            <!-- FileNoProcess the number of file to process each timer round -->

            <add key="FileNoProcess" value="3"/>

           

      </appSettings>

</configuration>

 

  1. จากนั้นเพิ่ม class เข้ามาใน project โดยตั้งชื่อว่า FileBackupService.cs และเพิ่ม code ใน table ข้างล่างนี้ ซึ่งจะเป็น Class ส่วนที่เกี่ยวข้องกับการ process file ทั้ง copy, move, delete และจะมีการบันทึกค่าลงใน EventLog ซึ่งClassนี้จะถูกเรียกใช้ใน windows service

using System;

using System.Collections.Generic;

using System.Text;

using System.Configuration;

using System.Diagnostics;

using System.Collections;

 

using System.IO;

using System.Timers;

 

namespace myService

{

    internal class FileBackupService

    {

 

        internal EventLog LogService = new EventLog();

        internal Timer ServiceTimer = new Timer();

        internal ArrayList queueFile = new ArrayList();

        internal FileSystemWatcher fsw = new FileSystemWatcher();

 

        string serviceMode = "";

        string targetFolder = "";

 

        int fileNoProcess = 0;

 

        internal void InitConfig()

        {

 

            serviceMode = ConfigurationManager.AppSettings["ServiceMode"];

            targetFolder = ConfigurationManager.AppSettings["TargetFolder"];

            fileNoProcess = int.Parse(ConfigurationManager.AppSettings["FileNoProcess"]);

 

            // file monitor config

            fsw.Filter = ConfigurationManager.AppSettings["FileFilter"];

            fsw.Path = ConfigurationManager.AppSettings["FileMonitoringPath"];

 

            fsw.EnableRaisingEvents = true;

            fsw.NotifyFilter = ((System.IO.NotifyFilters)

                ((((System.IO.NotifyFilters.FileName

                    | System.IO.NotifyFilters.DirectoryName)

                    | System.IO.NotifyFilters.Size)

                    | System.IO.NotifyFilters.LastWrite)));

 

            fsw.Created += new FileSystemEventHandler(fsw_Created);

 

 

            // timer config

            ServiceTimer.Interval = double.Parse(ConfigurationManager.AppSettings["ServiceTimer"]) * 1000;

            ServiceTimer.Enabled = true;

            ServiceTimer.Elapsed += new ElapsedEventHandler(ServiceTimer_Elapsed);

 

            // event log config

            LogService.Log = "Application";

            LogService.Source = "FileBackupService";

 

        }

 

        private void ServiceTimer_Elapsed(object sender, ElapsedEventArgs e)

        {

            ServiceTimer.Stop();

            if (queueFile.Count > 0)

                for (int i = 0; i < fileNoProcess; i++)

                {

                    if (queueFile.Count > 0)

                    {

                        ProcessFileList(queueFile[0].ToString());

                        queueFile.RemoveAt(0);

                    }

                    else

                    {

                        break;

                    }

                }

            ServiceTimer.Start();

        }

 

        private void ProcessFileList(string filepath)

        {

            switch (serviceMode)

            {

                case "0":

                    FileProcess(filepath, targetFolder, FileServiceAction.COPY);

                    break;

                case "1":

                    FileProcess(filepath, targetFolder, FileServiceAction.MOVE);

                    break;

                case "2":

                    FileProcess(filepath, targetFolder, FileServiceAction.DELETE);

                    break;

            }

        }

 

        private bool FileProcess(string pathFileTarget, string pathFileCopy, FileServiceAction action)

        {

 

            string filename = Path.GetFileName(pathFileTarget);

            string taskMessage = "";

 

            try

            {

                switch (action)

                {

                    case FileServiceAction.COPY:

                        taskMessage = "Copy ";

                        File.Copy(pathFileTarget, pathFileCopy + filename);

                        break;

                    case FileServiceAction.MOVE:

                        taskMessage = "Move ";

                        File.Move(pathFileTarget, pathFileCopy + filename);

                        break;

                    case FileServiceAction.DELETE:

                        taskMessage = "Delete ";

                        File.Delete(pathFileTarget);

                        break;

                }

                WriteEventLog(taskMessage + pathFileTarget + " : Successful. ", EventLogEntryType.Information);

                return true;

            }

            catch (Exception ex)

            {

                WriteEventLog(taskMessage + pathFileTarget + " : Error Message = " + ex.Message, EventLogEntryType.Error);

                return false;

            }

        }

 

        private void fsw_Created(object sender, FileSystemEventArgs e)

        {

            queueFile.Add(e.FullPath);

        }

 

        internal void WriteEventLog(string message, EventLogEntryType elet)

        {

            if (LogService != null)

            {

                LogService.WriteEntry(message, elet);

            }

        }

    }

 

    internal enum FileServiceAction

    {

        COPY,MOVE,DELETE

    }

}

 

 

  1. กลับมาที่ Service1.cs file เมื่อเปิดขึ้นมาแล้วใส่ code ลงไปตาม table ข้างล่างนี้ เพื่อทำการเรียกใช้ FileBackupService Class ที่ได้สร้างไว้ในขั้นตอนที่แล้ว

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Diagnostics;

using System.ServiceProcess;

using System.Text;

 

using System.Timers;

using System.Configuration;

using System.IO;

using System.Collections;

 

namespace myService

{

    public partial class Service1 : ServiceBase

    {

        private FileBackupService fbs;

 

        public Service1()

        {

            InitializeComponent();

            fbs = new FileBackupService();

        }

 

        protected override void OnStart(string[] args)

        {

            fbs.InitConfig();

            fbs.ServiceTimer.Start();

        }

 

        protected override void OnStop()

        {

            fbs.ServiceTimer.Stop();

            fbs = null;

        }

 

    }

}

 

 

  1. ต่อมาทำการเพิ่มตัว Installer Class ให้ Service ที่เราได้สร้างขึ้นมาดังนี้
    1. ไปที่ Solution Explorer เลือกที่ Service1.cs คลิ๊กขวาเลือก Open
    2. จากนั้นเปิดมาก็จะได้จอ เทา ๆ ให้คลี๊กขวาที่พื้นที่ของจอเทา ๆ แล้วเลือก Add Installer
    3. จากนั้นจะได้หน้าจอที่มี 2 components ปรากฎอยู่ตามรูปด้านล่างนี้

 

    1. จากนั้นให้เลือกที่ serviceProcessInstaller1 แล้ว config properties ตาม รูปข้างล่างนี้

    1. และเลือก serviceInstaller1 แล้ว config properties ตาม รูปข้างล่างนี้

  

  1. ทำการ build project และ ให้ไปใน folder bin ของ project ที่ build ได้มา
    1. จากนั้นทำการสร้าง bat file ด้วยการ new file เป็น text file แล้วเปิดขึ้นมาด้วย notepad หรืออะไรก็แล้วแต่ copy คำสั่งในตารางข้างล่างนี้ใส่ไป และ save as เป็นชื่อ InstallService.bat

%WINDIR%\Microsoft.NET\Framework\v2.0.50727\RegSvcs.exe myService.exe

 

NET START "FileBackupService"

 

โดยคำสั่งด้านบนนี้จะเป็นการเรียก utility ที่ชื่อ RegSvcs.exe มาทำการ install windows service ที่เราได้สร้างไว้ และเรียกคำสั่ง net start เพื่อให้ทำการ start service ของเรา

    1. ต่อมาสร้าง bat file ขึ้นมาอีกตัว สำหรับการ Uninstall Service ที่เรา install ไปโดยทำตามขั้นตอนของ a. ด้านบน แล้ว copy คำสั่งในตางรางด้านล่างนี้ไปวาง จากนั้น save as เป็น UninstallService.bat

NET STOP "FileBackupService"

 

%WINDIR%\Microsoft.NET\Framework\v2.0.50727\RegSvcs.exe /u myService.exe

 

 

 

 

โดยคำสั่ง NET STOP ด้านบนเป็นการหยุด Windows Service ของที่ยัง Start อยู่ก่อน

จากนั้นก็ใช้ Regsvcs.exe /u เพื่อทำการ uninstall

 

 


  1. ทำการทดลองใช้งาน Windows Service ที่เราสร้าง
    1. สร้าง folder ไว้ใน C:\Test\master ไว้สำหรับเป็น folder ที่จะมีมี file มาdrop เพื่อให้ตัว Service ทำ monitor file
    2. สร้าง folder ไว้ใน C:\Test\backup ไว้สำหรับให้ service ทำการ copy file จาก master folder มา drop ลงที่นี่เพื่อทำ backup
    3. จากนั้นเข้าไปใน Bin folder ของ project แล้วทำการ run InstallService.bat  file เพื่อเริ่มทำการ Install Windows Service ที่เราสร้างขึ้น
    4. จากนั้นไป หา file อะไรก็ได้ทำการ copy แล้วนำมา paste ลงใน C:\Test\master เพื่อทดสอบ
    5. หลังจาก paste เสร็จแล้วให้เข้าไปดูที่ C:\Test\backup จะเห็นว่ามี file ที่เรา paste ไว้ใน C:\Test\master เกิดขึ้นที่ C:\Test\backup นี้ด้วย
    6. หากมีอะไรผิดปกติให้เข้าไปเปิด EventLog ที่ Administrative Tools -> Event Viewers เลือกดูใน Application Group จะเห็นว่า Service ที่เราสร้างไว้มีการบันทึก Log เก็บไว้ตลอดตามรูปข้างล่างนี้

 

Download Source code here!

http://greatfriends.biz/files/WinService.rar

 
 

to be continued...

February 04

จะไป Seattle, USA วันที่ 11 - 16 มีนาคม 2550 <MVP Global Summit 2007>

2007 Microsoft Most Valuable Professional (MVP) Global Summit

Independent Experts. Real World Answers.

You are invited to attend the 2007 MVP Global Summit, scheduled for March 12-15, 2007 in Seattle at the Washington State Convention & Trade Center (WSCTC) and at Microsoft Corporation Headquarters in Redmond, Washington.

The 2007 MVP Global Summit will provide MVPs, Regional Directors (RDs), and special community influencers four days of activities and technical sessions in which you can exchange information with Microsoft executives and product managers, share best practices, network and have fun. We’re especially excited to have Microsoft Chairman Bill Gates kick off the event with a keynote address.

Although the link to Registration is second in the top menu bar, please review all the information before you register. This will help you make informed decisions while registering. Please complete your registration by February 16, 2007 to allow us to best meet any hotel requests.

We are thrilled that you will be joining us!

 

Agenda Overview

The MVP Summit will span 4 consecutive days starting on Monday, March 12th and ending on Thursday, March 15th. The first day will be devoted to Registration Check-In, the Expo and MVP Regional Dinners.

On Day 2, you’ll hear a keynote address by Bill Gates and attend several Platform sessions focused on industry relevant topics, key Microsoft products and technologies. We’ll close the day at a special attendee party at the Museum of Flight.

On Days 3 and 4, you will attend several technically focused sessions broken out by competency. On the evening of Day 3, you’ll attend a dinner hosted by a Product Group. Finally at the close of Day 4, we’ll gather together for lunch and to connect one last time with your MVP peers, MVP leads and others.

Day and Time

Location

Activity

Monday, March 12
13:00 - 17:00 PST

Washington State Convention & Trade Center (WSCTC)

Registration
Check-In

 

WSCTC

Microsoft Programs
and Services Expo

18:30 - 23:00 PST

Various Seattle hotels

MVP Regional Dinners

 

 

 

Tuesday, March 13
07:30 - 09:00 PST

WSCTC

Breakfast

 

09:00 - 10:15 PST

WSCTC

Keynote - Bill Gates

11:00 - 17:30 PST

WSCTC

Platform Sessions

18:30 - 23:00 PST

Museum of Flight

Attendee Party

 

 

 

Wednesday, March 14
07:00 - 8:30 PST

Microsoft Conference Center

Breakfast

08:30 - 17:00 PST

Microsoft - Redmond Campus
 and
Conference Center

Technical Sessions

18:30 - 22:00 PST

Microsoft Headquarters -
Redmond Campus - Cafes

Dinners Hosted by
Product Groups

 

 

 

Thursday, March 15
07:00 - 08:30 PST

Microsoft Conference Center

Breakfast

08:30 - 12:00 PST

Microsoft - Redmond Campus
 and
Conference Center

Technical Sessions

12:00 - 15:00 PST

Microsoft Conference Center

Lunch and
Wrap-up

 

HOTEL, Room and MAP

1900 5th Avenue · Seattle, Washington 98101 · United States · Phone: (206) 728-1000

http://www.starwoodhotels.com/westin/property/overview/index.html?propertyID=1055

 

 

Nine นาย Microsoft MVP Thailand

Occupation
Location
Interests
Microsoft MVP 2006
Profile on Microsoft:
https://mvp.support.microsoft.com/profile=7B504FF5-5A40-4EFB-9BD4-A4BC6DC74485

Windows Media Player

Pro BizTalk 2006
Pro WF: Windows Workflow in .NET 3.0
Windows Communication Foundation Unleashed
Windows Presentation Foundation Unleashed