Month: July 2016

  • Auto remove schema in EDMX on build

    Entity Framework (EF)  คือ data access technology ที่เริ่มเปิดตัวครั้งแรกเป็นส่วนหนึ่งของ .NET Framework 3.5 SP1 โดยตัว EF จะทำหน้าที่เป็น object-relational mapper ที่ทำให้ผู้พัฒนาไม่จำเป็นต้องเขียน code ในส่วน data access ก็สามารถใช้ข้อมูลจาก relational database โดยผ่าน object model

    การพัฒนาโปรแกรมโดยใช้ EF นั้นจำเป็นต้องมี Entity Data Model เป็น model ที่กำหนดรายละเอียดเกี่ยวกับ entity และ relationship ระหว่าง entity นั้นๆ การสร้าง Entity Data Model สามารถแยกออกเป็น 2 แนวทางคือ “Code First” เป็นการกำหนดรูปร่างของ model โดยการสร้าง class (เขียน code) จะมี database หรือไม่มีอยู่ก่อนก็ได้  และ “Database First” ที่จะทำการสร้าง model ( reverse engineer) จาก database ที่มีอยู่โดย EF Designer ซึ่ง model ที่ได้จะเก็บอยู่ใน EDMX file (.edmx) สามารถเปิดหรือแก้ไขเพิ่มเติมได้ด้วย EF Designer สำหรับ class ที่ใช้ในโปรแกรมจะถูกสร้างโดยอัตโนมัติจาก EDMX file

    ข้อมูล Entity Data Model ใน EDMX file อยู่ในรูปแบบ xml สามารถแบ่งออกเป็น 3 ส่วนคือ Storage model, Conceptual model และ Mapping ซึ่งในส่วนของ Storage model จะเป็นข้อมูลรายละเอียดของ entity จาก database เช่น

    ข้อมูล EntityType ที่ให้รายละเอียดของชื่อของ entity (table ใน database), ชื่อและประเภทของ property (column ของ table ใน database)

     <EntityType Name="VF_CONFIG_REPORT">
      <Key>
        <PropertyRef Name="ID" />
      </Key>
        <Property Name="ID" Type="number" Precision="38" Scale="0" Nullable="false" />
        <Property Name="REPORT_NAME" Type="varchar2" MaxLength="512" />
        <Property Name="REPORT_PATH" Type="varchar2" MaxLength="512" />
        <Property Name="GROUP_TYPE" Type="number" Precision="38" Scale="0" />
        <Property Name="SIGN_NUM" Type="number" Precision="38" Scale="0" />
        <Property Name="SIGNS" Type="varchar2" MaxLength="128" />
     </EntityType>

    ข้อมูล EntitySet ที่ประกอบด้วย ชื่อ,ประเภทของ entity, schema และ query ที่ใช้ดึงข้อมูล

    <EntitySet Name="VF_CONFIG_REPORT" EntityType="Self.VF_CONFIG_REPORT" store:Type="Views" store:Schema="FINANCE">
       <DefiningQuery>
          SELECT 
           "VF_CONFIG_REPORT"."ID" AS "ID",
           "VF_CONFIG_REPORT"."REPORT_NAME" AS "REPORT_NAME", 
           "VF_CONFIG_REPORT"."REPORT_PATH" AS "REPORT_PATH", 
           "VF_CONFIG_REPORT"."GROUP_TYPE" AS "GROUP_TYPE", 
           "VF_CONFIG_REPORT"."SIGN_NUM" AS "SIGN_NUM", 
           "VF_CONFIG_REPORT"."SIGNS" AS "SIGNS"
         FROM "FINANCE"."VF_CONFIG_REPORT" "VF_CONFIG_REPORT"   
       </DefiningQuery>
    </EntitySet>

    เมื่อมีการระบุ schema ของ entityใน EDMX file  นั่นทำให้การ deploy ระบบ(โปรแกรมและ database) จำเป็นต้องมี database ที่มี schema ชื่อเดียวกับที่กำหนดใน EDMX file เท่านั้น(schema ได้มาจากการ generate ของ EF Designer ในขั้นตอนการพัฒนาระบบ) ถ้าต้องการให้ EF ทำงานกับ database schema อื่นจะต้องแก้ไข schema ใน EDMX file ให้ตรงกัน หรือไม่ระบุ schema โดยลบส่วนที่ระบุ schema ออก ซึ่งการแก้ไขจะต้องทำการแก้ไขโดยตรงไปที่ EDMX file แล้วทำการ build ใหม่ (ในกรณีที่ไม่ได้เลือก build EDMX file เป็นแบบ embeded resource สามารถแก้ไขที่ .ssdl file ได้โดยไม่ต้อง build ใหม่)

    ในการเปลี่ยน schema ใน EDMX file นั้นจะต้องแก้ทุก EntitySet ที่มี ทำให้มีความเสี่ยงที่จะเกิดความผิดพลาดในการแก้ไข ทำให้ระบบไม่สามารถทำงานได้ และถ้ามีความจำเป็นต้องปรับ Entity Data Model เพื่อเพิ่ม, แก้ไข หรือลบ entity ใดๆ EF Designer จะทำการ update .EDMX file ใหม่ ทำให้ schema ที่แก้ไขไปแล้วกลับมาเหมือนเดิม ต้องเปลี่ยน schema ใหม่อีกครั้ง ก็ยิ่งจะเพิ่มความเสี่ยงที่จะเกิดความผิดพลาด และยุ่งยากในการบริการจัดการ source code

    เราสามารถทำให้กระบวนการแก้ไขหรือลบ schema ใน EDMX file เป็นไปโดยอัตโนมัติ โดยการแก้ใข .csproj เพิ่มกระบวนการแก้ไขหรือลบ schema เข้าไปในขั้นตอนการ build ของ MsBuild หลังจากกระบวนการ “EntityDeployEmbededResource” ของ EF ดังนี้

     

    <Target Name="RemoveSchemaEntityDeployEmbeddedResources" AfterTargets="EntityDeployEmbeddedResources" Condition="'@(EntityDeployEmbeddingItems)' != ''">
      <PropertyGroup>
        <RemoveSchemaEmbeddedResources>"Libs\EFRemoveSchema" $(EntityDeployIntermediateResourcePath)%(EntityDeployEmbeddedResources.EntityDeployRelativeDir)</RemoveSchemaEmbeddedResources>
      </PropertyGroup>
      <Exec WorkingDirectory="$(MSBuildProjectDirectory)" Command="$(RemoveSchemaEmbeddedResources)" />
    </Target>

    “Libs\EFRomoveSchema” เป็นโปรแกรมเล็กๆที่พัฒนาเพื่อลบ schema ใน Entity Data Model ที่อยู่ใน folder   $(EntityDeployIntermediateResourcePath)%(EntityDeployEmbeddedResources.EntityDeployRelativeDir) โดยใช้ เทคนิคการค้นหา attribute ของ node ที่ต้องการใน XML file (EDMX file) เพื่อลบ และบันทึกกลับลงไปที่ XML file นั้นๆ

     

    อ้างอิง : https://msdn.microsoft.com/en-us/data/ee712907

  • ทำความรู้จักและเรียนรู้การใช้งานเบื้องต้นกับ StringBuilder ใน .NET Framework(C#)

              โดยปกติแล้วนั้น ผู้พัฒนาโปรแกรมโดยใช้ .NET Framework มักจัดการข้อมูลที่เป็นอักษรหรือข้อความ (String) ด้วยคลาสของ String ที่มีใน .NET Framework ซึ่งประกอบไปด้วยฟังก์ชั่นหรือเมธอดที่หลากหลายที่ติดมากับตัวคลาส เพื่อเตรียมมาไว้ให้ใช้งาน และสามารถรองรับความต้องการในการจัดการข้อมูลของผู้ใช้แต่ละคน ซึ่งมีวิธีการใช้งานง่าย ไม่ยุ่งยากซับซ้อน มีมาตรฐานการใช้งานที่รู้จักโดยทั่วถึงกัน สะดวกและรวดเร็วทำให้ผู้พัฒนาสามารถเลือกวิธีจัดการข้อมูลได้อย่างมีประสิทธิภาพ อย่างไรก็ตาม แม้ว่าคลาสของ String จะมีเมธอดให้เราได้เลือกใช้กันอย่างมากมายและมีประสิทธิภาพอยู่แล้ว แต่ปัญหาอย่างหนึ่งที่พบในการใช้งานกับตัวแปรของคลาส String คือ การเชื่อมต่อหรือเปลี่ยนแปลงแก้ไขค่าข้อความของตัวแปรชนิด String ในแต่ละครั้ง จะไม่สามารถเปลี่ยนรูป หรือกลับไปแก้ไขค่าของตัวแปรบนพื้นที่หน่วยความจำเดิมที่ถูกจองไว้ให้กับตัวแปรได้ หรืออาจพูดในทางโปรแกรมแบบง่ายๆได้ว่า หากเราต้องการเปลี่ยนแปลงค่าของตัวแปรชนิด String เราจะไม่สามารถกลับไปแก้ไขค่าใน object ของตัวแปรที่ถูกสร้างขึ้นเดิมในหน่วยความจำ หรือ Memory ที่สร้างไว้ในตอนแรกได้ แต่จะมีการสร้าง object ตัวใหม่ขึ้นมา ทุกครั้งที่มีการแก้ไข/จัดการข้อมูลค่า หรือมีการใช้งานเมธอดในคลาส System.String และใช้วิธีให้ pointer ของตัวแปรชี้ไปยังตำแหน่งของ object ตัวใหม่ที่มีค่าของตัวแปรที่ถูกแก้ไขภายหลังแทน ซึ่งหากมีกรณีที่มีการเปลี่ยนแปลงค่าข้อมูล หรือเชื่อมต่อข้อความในตัวแปรดังกล่าวจำนวนหลายครั้ง หรือมีการวนลูปซ้ำในการเปลี่ยนแปลงค่าเป็นจำนวนมาก จะถือเป็นการใช้งานทรัพยากรหน่วยความจำอย่างสิ้นเปลือง เนื่องจาก object ของตัวแปรจะถูกสร้างขึ้นใหม่เรื่อยๆและมีการจองพื้นที่ให้กับ object ตัวที่ถูกสร้างขึ้นใหม่ตามจำนวนครั้งที่ทำการแก้ไขหรือเชื่อมต่อข้อความนั่นเอง ดังภาพ


    ภาพการจองพื้นที่ในหน่วยความจำของตัวแปรชนิด String
    [ที่มาของภาพ : http://www.tutorialsteacher.com/csharp/csharp-stringbuilder]

                        จากภาพตัวอย่างจะเห็นได้ว่า เดิมทีมีการกำหนดค่าให้กับตัวแปรเป็นข้อความ “Hello World!!” แต่เมื่อมีการปรับแก้ค่าของตัวแปร จะมีการสร้าง object ตัวใหม่ โดยจะเก็บค่าที่มีการเปลี่ยนแปลงของข้อความไปเป็น “Hello World!! From Tutorials Teacher” และเลื่อนตำแหน่งของ pointer ของตัวแปรที่จะชี้ไปเพื่อให้ได้ค่าใหม่นั่นเอง
              จากปัญหาดังกล่าว .NET Framework ก็ได้จัดเตรียมคลาสที่มีชื่อว่า “StringBuilder” ขึ้นมา ซึ่งเป็นคลาสที่ใช้ในการจัดการกับข้อมูลชนิดข้อความเช่นเดียวกับคลาส String โดยยินยอมให้มีการแก้ไขและปรับเปลี่ยนค่าในตัวแปรข้อความ(string) ดังกล่าวได้ใน object ตัวเดิมบนพื้นที่หน่วยความจำเดิม โดยไม่ต้องสร้าง object และทำการจองพื้นที่หน่วยความจำขึ้นใหม่ทุกครั้งที่มีการเปลี่ยนแปลงค่าของข้อความดังเช่นในคลาส String นั่นเอง ซึ่งจะทำให้สามารถประหยัดการใช้ทรัพยากรหน่วยความจำได้ในกรณีที่มีการเชื่อมต่อข้อความหรือเปลี่ยนแปลงค่าของตัวแปรจำนวนหลายครั้งได้

     ภาพการจองพื้นที่ในหน่วยความจำของตัวแปรชนิด StringBuilder

    [ที่มาของภาพ : http://www.tutorialsteacher.com/csharp/csharp-stringbuilder]

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

     

    หลักการทำงานและการจองพื้นที่ในหน่วยความจำของตัวแปรชนิด StringBuilder

              โดยปกติแล้วนั้น ค่าของ “StringBuilder.Length” จะเป็นค่าของจำนวนตัวอักษรที่มีในตัวแปร object ของ StringBuilder และจะถูกเพิ่มขึ้นเรื่อยๆ เมื่อมีการเพิ่มตัวอักษรหรืออักขระเข้าไปในตัวแปรนั้นโดยไม่มีการจองพื้นที่หน่วยความจำเพิ่ม จนกว่าค่าของ Length เท่ากับจำนวนของความจุที่จองพื้นที่หน่วยความจำไว้ ซึ่งก็หมายถึงค่าของ “Capacity” นั่นเอง และหากการเพิ่มตัวอักษรดังกล่าวทำให้ค่าของ Length มากกว่าค่าของ Capacity ใน object นั้นๆ จะมีการจองพื้นที่หน่วยความจำเพิ่มเป็นเท่าตัว เช่น จากเดิม 16 ตัวอักษรจะถูกเพิ่มเป็น 32 ตัวอักษร โดยจะสามารถเปลี่ยนแปลงได้ไม่เกินค่าความจุสูงสุด หรือที่เรียกว่า “MaxCapacity” ซึ่งถ้าหากมีการเพิ่มตัวอักษรที่เกินค่าของ MaxCapacity แล้วนั้นจะทำให้เกิดข้อผิดพลาดได้ แต่หากไม่มีการกำหนดค่าให้กับ Capacity และ MaxCapacity แล้วนั้น ค่าตั้งต้นของ Capactity เริ่มต้นจะอยู่ที่ 16 ตัวอักษร และค่าของ MaxCapacity จะอยู่ที่ประมาณ 2 พันล้านตัวอักษร หรือเทียบเท่ากับค่าสูงสุดของ Int32.MaxValue นั่นเอง

    การอ้างอิง Namespace
    โดย Namespace ที่ต้องอ้างอิงเพิ่มเติมในการใช้งานคลาส StringBuilder มีดังนี้

    • using System;
    • using System.Text;

    การประกาศตัวแปรของคลาส StringBuilder
    ในการประกาศตัวแปร object ของคลาส StringBuilder จะใช้หลักการเดียวกันกับการประกาศตัวแปร object ของคลาสโดยทั่วไป แต่สามารถประกาศโดยมีการระบุค่าอื่นเพิ่มเติมโดยใช้ Constructor ได้ ซึ่งจะขอยกตัวอย่างในกรณีที่มีการใช้งานกันโดยทั่วไป ดังนี้
    แบบเดียวกับการประกาศ object ของคลาสทั่วไป
    ตัวอย่าง

    StringBuilder sb = new StringBuilder();

    แบบมีการกำหนดค่าตั้งต้น
    ตัวอย่าง

    StringBuilder sb = new StringBuilder("Hello World!!");

    คำอธิบาย : เป็นการสร้างตัวแปร object แบบมีการกำหนดค่าเริ่มต้นให้มีค่าเท่ากับ Hello World!!
    แบบมีการระบุขนาดในการจองพื้นที่ของหน่วยความจำ(Capacity)  แม้ว่าตัวแปรของคลาส StringBuilder สามารถเพิ่มและขยายได้ไม่จำกัดโดยไม่ต้องสร้าง object ตัวใหม่ แต่ผู้พัฒนาสามารถระบุขนาดสูงสุดของจำนวนตัวอักษรที่ตัวแปรจะสามารถรองรับได้ โดยค่าดังกล่าวที่ระบุนี้ เรียกว่า “Capacity” และเรียกค่าของความยาวตัวอักษรที่มีในตัวแปรนั้นๆ โดยใช้ properties ที่มีชื่อว่า “Length” โดยหากมีการกำหนดค่าของ Capacity ให้กับตัวแปรคลาส StringBuilder เมื่อมีการแก้ไขค่าของตัวแปรจะไม่ถูกจองพื้นที่ใหม่จนกว่าความยาวของตัวอักษรจะถึงค่าของ Capacity ที่กำหนด จึงจะมีการจองพื้นที่ใหม่ให้อัตโนมัติในขนาดเดียวกับ Capacity ที่กำหนดไว้เดิมเป็นเท่าตัว แต่หากไม่ได้ทำการกำหนดค่าของ Capacity ไว้ จะมีค่า default เท่ากับ 16 ซึ่งสามารถกำหนดค่าของ Capacity ได้ดังนี้

    StringBuilder sb = new StringBuilder(25);

    คำอธิบาย : เป็นการสร้างตัวแปร object แบบมีการกำหนดขนาดของตัวแปรให้มีขนาดความจุ หรือ Capacity ไว้ที่ 25 ตัวอักษร แต่หากมีการกำหนดค่าของข้อมูลที่มีความยาวตัวอักษรมากกว่าขนาดที่กำหนด จะมีการขยายพื้นที่ความจุให้กับขนาดตัวแปรอัตโนมัติ นอกจากจะสามารถกำหนดขนาดของตัวแปร StringBuilder โดยใช้ Constructor แล้วนั้นยังสามารถระบุผ่าน Properties ที่มีชื่อว่า Capacityได้อีกด้วย ดังนี้

    sb.Capacity = 25;

    แบบกำหนดค่าเริ่มต้นและระบุขนาดความจุของตัวแปร
    ตัวอย่าง

    StringBuilder sb = new StringBuilder("Hello World!", 25);

    คำอธิบาย : เป็นการประกาศตัวแปรขนาด 25 ตัวอักษร และมีค่าเริ่มต้นเป็นคำว่า “Hello World!!”

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

    StringBuilder sb = new StringBuilder( 25,200);

    คำอธิบาย : เป็นจองพื้นที่ในการประกาศตัวแปร(Capacity)ขนาด 25 ตัวอักษร และมีค่าความจุสูงสุด(MaxCapacity)ได้ไม่เกิน 200 ตัวอักษร

    แบบกำหนดค่าเริ่มต้นที่มีการตัดข้อความ(substring) และระบุขนาดความจุของตัวแปร
    ตัวอย่าง

    StringBuilder sb = new StringBuilder("Hello World!",0,5, 25);

    คำอธิบาย : เป็นจองพื้นที่ในการประกาศตัวแปรขนาด 25 ตัวอักษร และมีค่าเริ่มต้นเป็นคำว่า “Hello”

    เนื่องจากมีการ substring ค่าข้อความ “Hello World!!” ตั้งแต่ตำแหน่งที่ 0 มา 5 ตัวอักษร จึงกลายเป็นคำว่า “Hello” นั่นเอง

    เมธอดที่จำเป็นและควรรู้ในการใช้งานคลาส String builder

    โดยแบ่งตามลักษณะการทำงาน เพื่อง่ายต่อความเข้าใจและการนำไปใช้ ดังนี้

    1.การเชื่อมต่อข้อความ เป็นการเชื่อมต่อข้อความกับค่าตัวแปรที่มีอยู่เดิมที่ตำแหน่งท้ายสุด ซึ่งมีเมธอดที่ใช้งานกันบ่อย ดังนี้
    • Append() เป็นเมธอดที่ใช้ในการเชื่อมข้อความ ซึ่งสามารถใช้แทนการต่อสตริงหรือข้อความแบบทั่วไปในคลาส String โดยจะไปต่อตรงส่วนท้ายสุดของค่าใน object โดยไม่ต้องเปลี่ยนการจองพื้นที่หน่วยความจำ
    ตัวอย่างที่ 1

    StringBuilder sb = new StringBuilder("Hello World!");
    sb.Append(" Nice to meet you!!");
    Console.WriteLine(sb);

    คำอธิบาย : จากตัวอย่างข้างต้น จะเห็นว่าเดิมค่าของตัวแปรมีค่า “Hello World!” แต่เมื่อมีการเรียกใช้เทธอด Append() จะทำการต่อข้อความจากเดิมจนกลายเป็น “Hello World! Nice to meet you!!

    ตัวอย่างที่ 2

    StringBuilder sb = new StringBuilder("Hello World");
    sb.Append(" !?!?",2,2);
    Console.WriteLine(sb);

    คำอธิบาย : จากตัวอย่างข้างต้น จะเห็นว่าเดิมค่าของตัวแปรมีค่า “Hello World” แต่เมื่อมีการเรียกใช้เมธอด Append() แบบมีการ substring ร่วมด้วย โดยจะเริ่มทำการตัดตัวอักษรจากข้อความ “ !?!?” จากตำแหน่งลำดับ index ที่ 2 ไป 2 ตัวอักษร ซึ่งนั่นก็คือ “?!” หลังจากนั้นก็จะเชื่อมต่อด้วยข้อความเดิมจนกลายเป็น “Hello World!?!

    AppendLine() เป็นเมธอดที่ใช้ในการแทรกบรรทัดใหม่เข้าไปให้กับตัวแปร
    ตัวอย่าง

    StringBuilder sb = new StringBuilder("Hello, I am Kate.");
    sb.AppendLine();
    sb.Append("Nice to meet you.");
    Console.WriteLine(sb);
    
    //หรือ
    StringBuilder sb = new StringBuilder("Hello, I am Kate.");
    sb.AppendLine("Nice to meet you.");
    Console.WriteLine(sb);
    
    

    คำอธิบาย : จากตัวอย่างข้างต้น จะเป็นการเพิ่มการขึ้นบรรทัดใหม่ให้กับข้อความของตัวแปร จากค่า “Hello, I am Kate.” ด้วยการขึ้นบรรทัดใหม่ ตามด้วยข้อความ “Nice to meet you.” โดยแสดงทั้งตัวอย่างที่มีการเพิ่มบรรทัดโดยใช้เมธอด AppendLine() ก่อน แล้วจึงเชื่อมข้อความที่เหลือด้วยเมธอด Append() หรืออาจรวบวิธีการขึ้นบรรทัดใหม่ต่อด้วยข้อความด้วยการใช้เมธอด Appendline() แบบมีการส่งค่าพารามิเตอร์ของข้อความที่ต้องการเชื่อมต่อหลังจากขึ้นบรรทัดใหม่ได้เลยดังตัวอย่าง

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

    int MyInt = 25;
    StringBuilder sb = new StringBuilder("Your total is ");
    sb.AppendFormat("{0:C} ", MyInt);
    Console.WriteLine(sb);
    

    คำอธิบาย จากตัวอย่าง เป็นการจัดรูปแบบของข้อมูลที่จะนำมาทำการเชื่อมต่อกับตัวแปรเดิม โดยผลลัพธ์ที่ได้ คือ Your total is $25.00 นั่นเอง

    Insert() เป็นเมธอดที่ใช้ในการเพิ่มค่าข้อความแทรกไปยังตัวแปร โดยมีการกำหนดตำแหน่งเริ่มต้นที่ต้องการให้แทรกเพิ่มในค่าข้อมูลดังกล่าวเข้าไปในตัวแปร StringBuilder นั้นด้วย
    ตัวอย่าง

    StringBuilder sb = new StringBuilder("Hello, I am Kate.");
    sb.Insert(5," Mr.Kim");
    Console.WriteLine(MyStringBuilder);

    คำอธิบาย : จากตัวอย่างข้างต้น จะเป็นการแทรกข้อความ “ Mr.Kim” ลงในตัวแปร sb ที่มีค่าเดิมเป็น
    Hello, I am Kate.” จนได้ผลลัพธ์ คือ “Hello Mr.Kim, I am Kate.”

    2.การล้างค่าหรือเอาค่าข้อมูลบางส่วนออก  เป็นการล้างค่าข้อมูลของตัวแปร หรือตัดข้อมูลของตัวแปรบางส่วนออกไป โดยเมธอดที่ใช้งานกันบ่อย มีดังนี้

    Clear() เป็นเมธอดที่ใช้ในการล้างค่าตัวอักษรในข้อความของตัวแปร String builder ดังกล่าว และกำหนดค่าให้กับความยาวตัวอักษรหรือ properties ที่มีชื่อว่า “Length เป็น 0
    ตัวอย่าง

    StringBuilder sb = new StringBuilder("Hello World!");
    sb.Clear();
    Console.WriteLine(sb);

    คำอธิบาย : จากตัวอย่างข้างต้นจะเป็นการล้างค่าข้อมูลให้กับตัวแปร sb จากเดิมที่มีค่าตั้งต้นเป็น “Hello World!” จะเหลือเป็นค่าว่าง หรือ String.Empty และหากต้องการให้แสดงผลจะไม่แสดงข้อความใดๆขึ้นมา แต่ยังคงจองพื้นที่หน่วยความจำไว้ให้กับตัวแปรนี้แม้จะไม่มีค่าข้อมูลใดๆก็ตาม และจะมีค่า Length เป็น 0 นั่นเอง

    Remove() เป็นเมธอดที่ใช้ในการตัดค่าของข้อความในตัวแปรออก โดยมีการกำหนดตำแหน่งเริ่มต้นและความยาวของตัวอักษรในข้อความที่ต้องการตัด โดยนับตำแหน่งจากตัวอักษรตัวแรกเป็นค่าตำแหน่งลำดับที่ 0(ซึ่งเป็นการอ้างอิงตามหลักการนับตำแหน่งของ index โดยเริ่มถือว่าตัวอักษรตัวแรกเป็น index ลำดับที่ 0 นั่นเอง)
    ตัวอย่าง

    StringBuilder sb = new StringBuilder("Hello World!");
    sb.Remove(5,7);
    Console.WriteLine(sb);
    

    คำอธิบาย : จากตัวอย่างข้างต้น เดิมตัวแปรมีค่าข้อความเป็น “Hello World!” แต่เมื่อใช้เมธอด Remove() ในการตัดค่าข้อความตั้งแต่ตำแหน่งของลำดับ index ที่ 5 (หรือตำแหน่งที่ 4 เมื่อเริ่มต้นนับ 1 จากตัวอักษรแรกของข้อความ) ไปจำนวน 7 ตัวอักษร โดยผลลัพธ์ที่ได้ เป็นดังนี้ “Hello

    • การตัดค่าบางส่วนออกโดยกำหนดค่า properties ที่ชื่อว่า Length ให้กับตัวแปร

    ตัวอย่าง

    StringBuilder sb1= new StringBuilder("Hello World!");
    sb1.Length--;
    //หรือ
    sb1.Length = sb1.Length-1;
    //หรือ
    sb1.Remove(sb1.Length-1,1);
    //เป็นการตัดค่าตัวอักษรตัวสุดท้ายออกจากข้อความ จะได้ผลลัพธ์ คือ Hello World 
    
    StringBuilder sb2= new StringBuilder("Hello World!"); 
    sb2.Length=0; 
    //เป็นการล้างค่าข้อมูลในตัวแปร sb2 
    ซึ่งจะมีลักษณะการทำงานเช่นเดียวกับการใช้เมธอด Clear() ที่กล่าวไว้แล้วข้างต้นนั่นเอง

    คำอธิบาย : จากตัวอย่างข้างต้น ในส่วนของ sb1 นั้นจะเป็นการตัดค่าตัวอักษรตัวสุดท้ายออกจากข้อความ “Hello World!” ซึ่งก็คือตัวอักษร “!” โดยจะได้ผลลัพธ์ เป็น “Hello World” และสำหรับกรณีของ sb2 จะเป็นการล้างค่าข้อมูลในตัวแปร sb2 ซึ่งจะมีลักษณะการทำงานเช่นเดียวกับการใช้เมธอด Clear() ที่กล่าวไว้แล้วข้างต้นนั่นเอง

    3. การเปลี่ยนแปลงค่าของตัวแปร  ดังนี้

    • Replace() เป็นเมธอดที่ใช้ในการแทนที่ข้อความ โดยมีลักษณะการทำงานเช่นเดียวกับเมธอด Replace() ที่มีในคลาส String ที่จะต้องมีการกำหนดค่าใหม่ที่ต้องการให้แทนที่ และค่าที่ต้องการแทนที่นั่นเอง
    ตัวอย่าง

    StringBuilder sb= new StringBuilder("Hello World!");
    sb.Replace('World', 'Kate');
    Console.WriteLine(sb);
    

    คำอธิบาย จากตัวอย่างข้างต้น จะเป็นการแทนที่ค่าของข้อความเดิมคือ “World” ในคำว่า “Hello World!” ด้วยค่า “Kate” ซึ่งจะได้ผลลัพธ์ คือ “Hello Kate!

    4. การแปลงค่าจากตัวแปรชนิด StringBuilder เป็น String  ดังนี้

    ToString() เป็นเมธอดที่ใช้ในการแปลงค่าตัวแปรแบบ StringBuilder มาเป็นค่าของตัวแปรแบบคลาส String เพื่อนำไปแสดงผลหรือนำมาประยุกต์ใช้งานกับเมธอดที่มีในคลาส String ต่อไป
    ตัวอย่าง

    StringBuilder sb= new StringBuilder("Hello World!");
    Console.WriteLine(sb.ToString());
    //การนำไปใช้กับเมธอดหรือฟังก์ชั่นที่มีในคลาส String
    int a = sb.ToString().IndexOf("a");
    //เป็นการค้นหาตำแหน่งของอักษร a ในตัวแปร sb ที่ถูกแปลงเป็น String 
    ซึ่งผลลัพธ์ที่ได้จะเท่ากับ -1 เนื่องจากไม่มีตัวอักษร a ในข้อความดังกล่าว

    คำอธิบาย : จากตัวอย่างข้างต้นเป็นการแปลงค่าของตัวแปรในคลาส StringBuilder ให้เป็นคลาส String ซึ่งหลังจากที่ได้ทำการแปลงค่าแล้วนั้น จะสามารถใช้งานเมธอหรือฟังก์ชั่นที่มีในคลาส String ได้ เช่น IndexOf หรือ StartsWith  เป็นต้น

    5. การอ้างอิงและเข้าถึงตัวอักษรที่อยู่ในข้อความ  ดังนี้

    ตัวอย่าง

    StringBuilder sb= new StringBuilder("Hello World!");
    Console.WriteLine(sb[6]);
    //ผลลัพธ์ที่ได้คือ "W"
    sb[2] = 'k';
    //ผลลัพธ์ที่ได้คือ "Heklo World!"

    คำอธิบาย : จากตัวอย่างข้างต้นเป็นการเข้าถึงตำแหน่งของค่าตัวแปรชนิด StringBuilder ผ่านการอ้างลำดับ index ของอักขระในตัวแปรนั้น และตัวอย่างถัดมาจะเป็นการเปลี่ยนแปลงค่าโดยการเข้าถึงอักขระในลำดับ index ที่กำหนด โดยให้ค่าใหม่แทนที่

    6. การค้นหา  ในการค้นข้อมูลของตัวแปรแบบ StringBuilder นั้น โดยทั่วไปแล้วจะไม่มีเมธอดที่ใช้ในการค้นหาข้อมูลโดยตรง ดังเช่นที่มีในคลาส String เช่น IndexOf หรือ StartsWith ดังนั้นเราสามารถประยุกต์วิธีการค้นหาตามลักษณะของข้อมูลและการจัดการได้ ดังนี้

    • การค้นหาค่าที่ได้กลับมาในรูปแบบ Stringจากการเรียกใช้เมธอด ToString() โดยใช้เมธอดที่มีเช่นเดียวกับในคลาส String ซึ่งเป็นวิธีที่ง่าย และสามารถเปลี่ยนแปลงข้อมูลของตัวแปรได้โดยไม่สิ้นเปลืองทรัพยากร
    • แปลงค่าของตัวแปรแบบ StringBuilder ให้เป็นแบบ String และใช้เมธอดในการค้นหาที่มีในคลาส String ซึ่งวิธีการนี้เหมาะกับการทำงานที่ไม่มีการเปลี่ยนแปลงภายหลังจากการแปลงค่ามากนัก เพื่อลดการสิ้นเปลืองทรัพยากรในการแปลงค่าภายหลัง
    • ค้นหาข้อมูลให้เสร็จก่อนทำการนำมาแปลงค่าเป็นแบบ StringBuilder โดยวิธีนี้จะต้องไม่สนใจค่าลำดับของตัวอักษรที่ได้จากการค้นหานั้นๆ
    • ค้นหาโดยใช้ Properties ทีชื่อว่า Chars โดยวิธีนี้เหมาะกับข้อมูลที่มีอักษรจำนวนไม่มาก และเงื่อนไขในการค้นหาไม่ซับซ้อน

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

    • ในการเรียกใช้งานเมธอดต่างๆ สามารถนำมาเขียนรวมกันใน statement เดียวกันได้ ดังนี้

    ตัวอย่างที่ 1

          StringBuilder sb = new StringBuilder();
          sb.Append("This is the beginning of a sentence, ");
          sb.Replace("the beginning of ", "");
          sb.Insert(sb.ToString().IndexOf("a ") + 2, "complete ");
          sb.Replace(",", ".");
          Console.WriteLine(sb.ToString());
    

    คำอธิบาย : จากตัวอย่างข้างต้นเป็นการเชื่อมต่อข้อความเริ่มต้น คือ “This is the beginning of a sentence, ” และแทนที่คำว่า  “the beginning of” ด้วย “”(ค่าว่าง) และแทรกข้อความคำว่า “complete ” เข้าไปในตำแหน่งซึ่งหามาได้จากการเรียกใช้เมธอด ToString() และตามด้วยเมธอด IndexOf ของตำแหน่งข้อความ “a ” ถัดไปอีก 2 ตำแหน่งด้วยค่า “complete ” และแทนที่เครื่องหมาย “,” ด้วย “.”

    สามารถเขียนรวมเป็น statement เดียวกันได้ดังนี้

    ตัวอย่างที่ 2

          StringBuilder sb = new StringBuilder("This is the beginning of a sentence, ");
          sb.Replace("the beginning of ", "").Insert(sb.ToString().IndexOf("a ") + 2, 
                                                     "complete ").Replace(",", ".");
          Console.WriteLine(sb.ToString());

    ซึ่งจะให้ผลลัพธ์เช่นเดียวกับตัวอย่างที่ 1

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

    แหล่งข้อมูลอ้างอิง :
    http://www.dotnetperls.com/stringbuilder
    https://msdn.microsoft.com/en-us/library/2839d5h5(v=vs.110).aspx
    http://www.tutorialsteacher.com/csharp/csharp-stringbuilder
    https://blog.udemy.com/stringbuilder-c-sharp/

  • ASP.NET MVC Part 4: ทำความรู้จักกับ ViewData, ViewBag และ TempData

    การส่งผ่านข้อมูลระหว่างกันใน ASP.NET MVC จะมีการส่งผ่านกันด้วย objects ซึ่งใน ASP.NET MVC จะมี object ที่ชื่อ ViewData, ViewBag และ TempData เป็น object ที่่ใช้ในการส่งผ่านข้อมูลในลักษณะที่แตกต่างกันออกไป โดยในการส่งผ่านข้อมูลจะแบ่งได้เป็น 3 กรณี คือ

    • การส่งผ่านค่าจาก Controller ไปยัง View
    • การส่งผ่านค่าจาก Controller หนึ่ง ไปยัง Controller อื่น
    • การส่งค่าระหว่าง Action หนึ่ง ไปยัง Action อื่น

    โดยทั้ง 3 objects จะมีคุณสมบัติที่แตกต่างกัน ดังนี้

    1. ViewBag เป็น dynamic object ในการส่งค่าจาก controller ไปยัง view
    2. ViewData เป็น dictionary object ในการส่งค่าจาก controller ไปยัง view
    3. TempData เป็น dictionary object ในการส่งค่าข้ามกันระหว่าง controller และ action

     

    การส่งผ่านข้อมูลจาก controller ไปยัง View

    การส่งผ่านข้อมูลจาก Controller ไปยัง View สามารถทำได้ 3 รูปแบบ ขึ้นอยู่กับลักษณะของข้อมูลที่ต้องการส่งว่าเป็นข้อมูลลักษณะไหน มีความซับซ้อนเพียงใด แต่ละรูปแบบสามารถเขียนได้ดังนี้

    controllertoview

     

    ส่งผ่าน Model

    การส่งผ่านข้อมูลผ่านตัว model เป็นการส่งผ่านข้อมูลผ่านตัว model ตรงๆ โดยที่ข้อมูลจะมี property ตามที่มีอยู่ใน model ที่สร้างไว้ ดังตัวอย่าง สร้าง model ของ Book และ set ค่าให้กับ property ต่างๆ และ return model Book ไปยังหน้า View

    ฝั่ง Controller

    public ActionResult Index()
            {
                List<ฺBook> b = new List<Book>() {
     
                   new Book{ Id = 1, Title = "Harry Potter", Author= "JK. Rolling"},
                   new Book{ Id = 2, Title = "Inferno", Author= "Dan Brown"}
                };
     
                return View(b);
            }
    

    ฝั่งแสดงผล View

    ประกาศ type ของ model เป็น Book หลังจากนั้นใช้ตัวแปร model ในการเข้าถึง property ต่างๆของ Model

    @model MvcBook.Models.Book
    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Title)
            th>
            <th>
                @Html.DisplayNameFor(model => model.Author)
            th>
            <th>th>
        tr>
     
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Title)
            td>
            <td>
                @Html.DisplayFor(modelItem => item.Author)
            td>
        tr>
    }
     
    table>
    

     

    ส่งผ่าน ViewBag

    การส่งผ่านข้อมูลด้วย ViewBag จะเป็นการส่งข้อมูลที่เป็น dynamic object เช่น string, int, float เป็นต้น ดังตัวอย่าง

    ฝั่ง Controller

    public ActionResult Index()
            {
                ViewBag.title = "THE DAVINCI CODE";
                return View();
            }
    

    ฝั่งแสดงผล View

    <h2>@ViewBag.Title</h2>
    

     

    ส่งผ่าน ViewData

    การส่งผ่านข้อมูลด้วย ViewData จะเป็นการส่งข้อมูลที่เป็น dictionary object เช่น List, Enumerable, array เป็นต้น ดังตัวอย่าง

    ฝั่ง Controller

    public ActionResult Index()
            {
                List<string> listBook = new  List<string>();
                listBook.Add("Davinci code");
                listBook.Add("The lost symbol");
                listBook.Add("Inferno");
                ViewData["ListBook"] = listBook;
                return View();
            }
    

    ฝั่งแสดงผล View

    ในการแสดงผลข้อมูลที่เป็น dictionary object นั้นให้ทำการ cast ให้เป็น type ที่ตรงกับ type ที่ส่งมาจาก controller

    <table class="table"> 
    @foreach (var item in (List<string>)ViewData["ListBook"]) {
        <tr>
            <td>
                @item
            td>
        tr>
    }
    <table>
    

     

    การส่งผ่านข้อมูลจาก controller/Action หนึ่ง ไปยัง controller/Action อื่น

    ในการส่งผ่านข้อมูลจาก controller หนึ่ง ไปยังอีก controller หรือจาก action ไปยังอีก action จะใช้ object ที่ชื่อ TempData ในการส่งค่าระหว่างกัน ซึ่ง TempData จะเก็บข้อมูลใน session โดยเป็นการส่งค่าจาก HTTP request หนึ่งไปยัง HTTP request อื่นๆ ดังตัวอย่าง

    tempdata

    controller ฝั่งส่งค่า

    public ActionResult Index()
            {
              TempData["data1"] = "I am from action 1";
              return RedirectToAction("Read");
             
            }
    

    controller ฝั่งรับค่า

    public string Read()
            {
                string str;
                str = TempData["data1"].ToString();
                return str;
            }
    

     

    สรุป

    ในการส่งข้อมูลระหว่าง controller กับ view และ controller/action กับ controller/action ของ ASP.NET MVC นั้น ในเบื้องต้นสามารถส่งผ่าน object ทั้ง 3 ตัว ได้แก่ ViewBag, ViewData และ TempData โดยในการเลือกใช้ให้พิจารณาลักษณะของข้อมูลที่ต้องการส่งเป็นหลัก

    บทความก่อนหน้า : ASP.NET MVC Part3: สร้าง Model ด้วย Entity Framework

    แหล่งอ้างอิง : 

    [1] http://www.codeproject.com/Articles/476967/What-is-ViewData-ViewBag-and-TempData-MVC-Option?msg=4858421

    [2] http://rachelappel.com/when-to-use-viewbag-viewdata-or-tempdata-in-asp-net-mvc-3-applications/

  • ตอนที่ 3 : สร้างรายงานด้วย Business Intelligence Development Studio (BIDS)

         เครื่องมือที่ใช้สำหรับสร้างรายงาน ได้แก่ Business Intelligence Development Studio (BIDS) และ Report Builder ในตอนที่นี้จะกล่าวถึงการสร้างรายงานด้วย BIDS ซึ่งเป็นอินเตอร์เฟซ ของ Microsoft Visual Studio เหมาะสำหรับนักพัฒนาที่คุ้นเคยกับ Microsoft Visual Studio ส่วน Report Builder เป็นโปรแกรมสำหรับสร้างรายงาน เหมาะกับผู้ใช้ทั่วๆไปที่ใช้ในทางธุรกิจเป็นหลัก

    การสร้างรายงานมีขั้นตอน ดังต่อไปนี้

    ขั้นตอนที่ 1 : Create Report Server Project

    • ไปที่ File > New > Project… ดังรูปที่ 1
    • จะได้ผลลัพธ์ ดังรูปที่ 2

    3-1

    รูปที่1 Create Report Server Project

    3-2

    รูปที่2 Report Server Project Solution

    ขั้นตอนที่ 2 : Create new report 
    การสร้างไฟล์รายงาน เราสามารถทำได้ 2 แบบคือ

     แบบที่1 สร้างไฟล์รายงานว่างๆ (empty report) ดังนี้

     1. จากรูปที่ 2 คลิกขวาที่โฟลเดอร์ Report > Add > New Item… > เลือก Create a new empty report ดังรูปที่ 3

    3-3

      รูปที่3 Create a new empty report

    2. ไปที่หน้าต่าง Report Data (View > Report Data) เพื่อสร้าง Data Sources และ Datasets

             – คลิกขวาโฟลเดอร์ Data Sources > Add Data Source… ซึ่งสามารถสร้าง Connection ได้ 2 แบบ คือ

              1. Embedded Connection เป็นการฝัง Connection String ไปในตัวรายงาน ดังรูปที่ 4

                3-5

           รูปที่4 Embedded Connection Properties

              2. Use Shared Data Sources Connection ซึ่งผู้ใช้จะต้องไปสร้าง Connection String ไว้ก่อน โดยเข้าไปที่หน้าต่าง Solution Explorer คลิกขวาโฟลเดอร์ Shared Data Sources > Add New Data Source ก็จะเข้าสู่หน้าจอสร้าง Connection ดังรูปที่ 4 ข้อดีของการใช้ Shared Data Sources คือเมื่อมีการเปลี่ยน Connection String สามารถเปลี่ยนที่เดียวไม่ต้องไล่เปลี่ยนทีละรายงาน และ Deploy เฉพาะ Shared Data Sources

              3. ไปที่หน้าต่าง Report Data คลิกขวาโฟลเดอร์ Datasets จะปรากฏหน้าต่าง Dataset Properties ดังรูปที่ 5

                3-6

                          รูปที่5 Dataset Properties

    ประกอบด้วย

        – Query เป็นส่วนสร้าง query โดยผู้ใช้สามารถเลือก Dataset, Data Source และประเภทของ query (Text, Table / View, Stored Procedure หรือ Import Query File – *.sql,*.rdl) จากรูปที่ 5 เมื่อกดปุ่ม Query Designer… จะปรากฏหน้าจอดังรูปที่ 6

           3-7

                       รูปที่6 Query Designer

        จากรูปที่ 6 ในหน้าจอประกอบด้วยส่วนหลักๆ 4 ส่วน ได้แก่ Diagram Pane ที่จะแสดง Table / View ซึ่งสามารถ Add / Remove Diagram โดยกดปุ่ม 3-7-1 จะปรากฏหน้าต่างแสดงรายชื่อ Table / View ทั้งหมดในระบบมาให้ผู้ใช้เลือก และผู้ใช้สามารถเชื่อม (Join) หลายๆตารางได้

        – Fields เป็นส่วนแสดงฟิลด์ข้อมูลที่เลือกมา (Select) ซึ่งผู้ใช้สามารถตั้งชื่อ Field Name ได้ ดังรูปที่ 7

           3-7-2

              รูปที่7 Dataset Properties-Fileds

        – Filters เป็นการกรองข้อมูลที่ได้จากการ query อีกที มีประโยชน์ตอนที่ใช้ Shared Dataset ร่วมกันหลายๆรายงาน ดังรูปที่ 8

           3-7-4

             รูปที่8 Dataset Properties-Filters

        – Parameters โปรแกรมจะ Generate ให้ Auto ตอนที่ผู้ใช้เขียนเงื่อนไขในของการ query ตัวอย่างเช่น ในรูปที่ 6 มีเงื่อนไขว่า “WHERE BUDGET_YEAR = :budget_year” (ในกรณีที่ผู้ใช้สร้างตัวแปลจากหน้าต่าง Report Data > Parameters แล้วนั้นจะต้องเลือก “Parameter Value” ให้ถูกต้อง) ดังรูปที่ 9

           3-7-5

          รูปที่9 Dataset Properties-Parameters

    4.  ไปยังหน้าต่าง Toolbox (View > Toolbox) ดังรูปที่ 10

            4

                          รูปที่10 Toolbox

    ตัวอย่าง สร้างตารางเบิกจ่ายประจำปีงบประมาณ

    –  ลาก Table จาก Toolbox ทางซ้ายมือมาวางบนรายงาน ดังรูปที่ 11 คลิกมุมตารางด้านซ้าย จะปรากฏหน้าจอ Tablix Properties ดังรูปที่ 12 จากนั้นเลือก Dataset name กดปุ่ม “OK”

    4-1

                      รูปที่11 Table

    4-2

               รูปที่12 Tablix Properties

    – เลือกฟิลด์ที่ต้องการแสดงมาใส่ใน Table จัดรูปแบบตามที่ต้องการ ดังรูปที่ 13 และกด Preview เพื่อดูข้อมูล จะช่วยให้ผู้ใช้สามารถเรียกรายงานได้ทันที โดยไม่ต้อง Deploy ขึ้น Report Server ถ้ารายงานมีการระบุพารามิเตอร์ จะขึ้นหน้าจอให้กรอกข้อมูลก่อน ดังรูปที่ 14 ซึ่งถ้าหากไม่ได้กำหนดพารามิเตอร์รายงานจะแสดงผลทันที

    4-3

                     รูปที่13 Design

    4-4

                     รูปที่14 Preview

    สำหรับแบบที่ 2 ใช้ Report Wizard เป็นตัวช่วยสร้างรายงาน จะขอกล่าวถึงในตอนถัดไปค่ะ…

     

  • การเขียนโปรแกรม JSP เชื่อมต่อ ORACLE

         JSP หรือชื่อเต็มว่า Java Server Page เป็นภาษาที่ใช้ในการพัฒนา Application ที่ทำงานบนเว็บไซต์ โดยรูปแบบการทำงานจะทำงานคล้ายกับภาษา  ASP ,PHP และ .Net รูปแบบการทำงานจะแตกต่างกันตรงที่ JSP เป็น Subset ของภาษา Java โดยรูปแบบการเขียนนั้นจะใช้รูปแบบคำสั่งและชุด SDK ของ Java และใน JSP จะมีนามสกุลของไฟล์เป็น .jsp โดยการทำงานจะทำงานในรูปแบบของ Server และ Client แสดงผลและโต้ตอบกับ User Interface ผ่าน Web Browser เช่น  IE ,Chrome ,Firefox และอื่นๆ โดยจะสามารถทำงานร่วมกับ Client Tags เช่นพวก HTML / JavaScript / CSS และพวก jQuery ให้ได้ผลลัพธ์ตามที่ต้องการ ที่สำคัญ JSP สามารถใช้งานได้ฟรี และสามารถรองรับได้ทุก Platform ไม่ว่าจะเป็น Windows ,Linux และ iOS รวมทั้ง Software อื่น ๆ

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

         เริ่มต้นในการเขียนโปรแกรมที่นิยมการ connect  oracle ด้วย jsp จะใช้การ connect  ด้วย  JDBC โดยในส่วน ภาษา jsp จะสามารถใช้ packet ของ java ที่จะสามารถ import class ของ JDBC มาใช้งานใน  jsp ได้ทันที โดยไม่จำเป็นต้องเขียน โปรแรกม เพิ่มเติมให้ยุ่งยาก

     

    ขั้นตอนที่ 1 สร้างไฟล์ jsp โดยข้อมูลภายในจะมีsyntax เหมือนกับ HTML แต่ต่างกันที่นามสกุลไฟล์ จะเป็นนามสกุล .jsp

    <HTML>
    <HEAD>
    <TITLE>Simple JSP to Oracle connection Example</TITLE>
    </HEAD>
    <BODY>
    </BODY>
    <HTML>
    

    ขั้นตอนที่ 2 ทำการ import library ที่ใช้ในการเชื่อมต่อกับ database oracle ด้วย java.sql.*

    <%@ page import="java.sql.*" %>
    
    <HTML>
    <HEAD>
    <TITLE>Simple JSP to Oracle connection Example</TITLE>
    </HEAD>
    <BODY>
    </BODY>
    <HTML>
    

    ขั้นต้อนที่ 3 สร้างตัวแปลที่ใช้ในการเขื่อมต่อ

    String strdrive ="oracle.jdbc.OracleDriver";   //driver ของ oracle
    String url = "jdbc:oracle:thin:@localhost:1521:xe";  //server database
    String usr = "username";  //user name
    String pwd = "pwd";     //password 

    ขั้นต้อนที่ 4 สร้าง connection การเชื่อมต่อไปยัง database

    Connection conn = null;

    ขั้นตอนที่ 5 ทำการเชื่อมต่อกับ database โดยใช้ ตัวแปลจากข้างต้น

    <%
        Connection conn = null;
        try
        {
            Class.forName(strdrive );
            conn = DriverManager.getConnection(url, usr, pwd);
            out.println("connected....!!");
    
        }
    
        catch(Exception e)
        {
            out.println("Exception : " + e.getMessage() + "");
        }
    
    
    %>

    ขั้นตอนที่6 ต้องสร้างตัวแปลเพื่อใช้ในการประมวลผล

    Statement st; // ใช้ในการรับคำสัง sql
    ResultSet rs;  //เก็บข้อมูลที่ได้ขาการประมวลผล
    

    ขั้นตอนที่ 7 ทดสอบการทำงาน

    String SQL="select T1 from table";
    rs=st.executeQuery(SQL);
           while(rs.next())
           {
              out.println("number is: "+rs.getString(1));%>          
           } 

     

  • การตั้งค่าให้ Android Emulator สามารถรัน google map ได้

    โดยปกติ Android Emulator ไม่สามารถรัน google map เนื่องจากไม่มีในส่วนของ google play serivce นั้นเอง (สังเกตุ ได้ว่าไม่มีแอพพลิเคชั่น google play) ซึ่งเมื่อนักพัฒนาทำการพัฒนาแอพพลิเคชั่นที่มีgoogle map และรองรันบน Android emulator  จะเกิดข้อผิดพลาดดังรูป
    1

    ในบทความนี้ขอนำเสนอวิธีการที่ทำให้ Genymotion ซึ่งเป็น Andriod  Emulator ตัวหนึ่งที่นิยมใช้กัน เนื่องจากทำงานได้รวดเร็ว และทำงานได้ดีกับ Android Studio 🙂

    โดยหลักการก็ไม่มีอะไรมาก เมื่อ Android emulator ของเราไม่มี google play service เราก็แค่ลงไปให้ซะเลย

    1. ขั้นแรก ต้องโหลดไฟล์ที่ใช้ในการติดตั้ง ดังรูป2

      โดยในส่วนของไฟล์ gapps-jb-xxxx-signed ต้องโหลดเวอร์ชั่นให้ตรงกับ android แต่ละเวอร์ชั่นที่ใช้งาน

    2. ต่อไปทำการติดตั้อง Genymotion-ARM-Translation_v1.1.zip ก่อน ซึ่งการติดตั้งก็ง่าย ๆ โดยการลากไฟล์ไปวางที่ Emulator ได้ทันที่ รอจนติดตั้งเสร็จและทำการ Restart Emulator
    3. ต่อไปก็ทำการ Gapps และ Restart Emulator อีกครั้ง เป็นอันเสร็จเรียบร้อย
    4. ลองเปิด Emulator จะพบว่ามีแอพพลิเคชั่น google play เรียบร้อยแล้ว ลองรันทดสอบแอพพลิเคชันที่มี google map ดูได้เลย

    3

  • IEEE Explore Services and IPv6

    หลายวันก่อน (2016-06-28) คุณวันชัย พบปัญหาการเข้าใช้งาน web ieeexplore.ieee.org

    p1

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

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

    หลังจากผ่านการตรวจสอบ 2-3 ขั้นตอนก็ได้ข้อสรุปว่า ปัญหาที่เกิดขึ้นก็คือ จากเดิมทีที่เครือข่ายของมหา’ลัย ใช้งาน IPv4 ในการเข้าถึงเครือข่ายของ IEEE (สำหรับในกรณีนี้ก็คือ ieeexplore.ieee.org) ตอนนี้ เมื่อเครือข่ายของ มหาวิทยาลัยสงขลานครินทร์ พร้อมที่จะให้บริการ IPv6 เครื่องคอมพิวเตอร์ ซึ่งส่วนใหญ่พร้อมที่จะใช้ IPv6 อยู่แล้ว ก็จะเปลี่ยนไปใช้ IPv6 สำหรับการติดต่อกับเครือข่ายปลายทาง

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

    อย่างไรก็ตาม สำหรับกรณีนี้ บริการของ IEEExplore และ Academic Journals อีกจำนวนมากซึ่งมหาวิทยาลัยสงขลานครินทร์เป็นสมาชิกอยู่ (ซึ่งอาจจะเป็นสมาชิกโดยตรง หรือโดยอ้อมผ่านทาง UniNet/สกอ.) ไม่ได้เป็นบริการที่เปิดแบบ public ให้ใครๆก็สามารถเข้าถึงข้อมูลได้ทุกอย่าง ข้อมูลบางอย่าง เช่น ไฟล์ของบทความ จะดาวน์โหลดได้เฉพาะสมาชิกเท่านั้น ถ้าเป็นสมาชิกแบบบุคคล วิธีการที่ใช้ในการยืนยันตัวตน ก็คือการ login โดยใช้ username และ password แบบเดียวกับที่ใช้กับบริการบนเว็บอื่นๆทั่วไป แต่สำหรับสมาชิกแบบ “สถาบัน” แบบที่มาหวิทยาลัยสงขลานครินทร์เป็นอยู่ แทนที่จะต้องให้ นักศึกษาและบุคคลากร แต่ละคนจะต้องมีแอคเคาท์ เป็นของตัวเอง วิธีการที่ง่ายกว่าก็คือ ใช้หมายเลข IP เป็นตัวระบุ โดยสถาบันที่เป็นสมาชิก ก็จะต้องแจ้งไปทางผู้ให้บริการว่า หมายเลข IP ใด หรือ ช่วงใดบ้างที่เป็นของสถาบันนั้นๆ

    แน่นอนว่าก่อนหน้านี้ หมายเลข IP ที่มหาวิทยาลัยสงขลานครินทร์แจ้งไปจะมีเฉพาะ IPv4

    และแน่นอนว่าก่อนหน้านี้ไม่มีใครแจ้งปัญหาว่าสามารถดาวน์โหลดไฟล์จาก IEEExplore ไม่ได้ … เพราะเครือข่ายส่วนใหญ่ใน มหา’ลัย ใช้งานได้เฉพาะ IPv4

    [[

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

    ย้ำ, ผมไม่ได้ตั้งข้อสงสัยใดๆทั้งสิ้นจริงๆ

    EDIT (2016-07-08): ข้อมูลจาก ที่นี่ ทำให้พอเชื่อได้ว่า IEEE เริ่มใช้งาน IPv6 เมื่อประมาณ 2016-06-06 นั่นคือประมาณ 1 เดือนที่แล้ว ดังนั้นปัญหาในการเข้าถึงบริการของ IEEE Explore จากเครือข่ายของ มหาวิทยาลัยสงขลานครินทร์ โดยใช้งาน IPv6 แล้วใช้งานไม่ได้ จึงไม่ได้นานมากอย่างที่ผมคิดตอนแรก
    ]]

    กลับมาที่เรื่องของการใช้งาน IEEExplore ต่อ ปัญหาที่เกิดขึ้นครั้งนี้ เทียบเคียงได้กับการที่ทาง มหาวิทยาลัยแจ้ง IP address ที่มีใช้งานอยู่ให้กับทางผู้ให้บริการไม่ครบ เมื่อเครื่องคอมพิวเตอร์เริ่มใช้งาน IPv6 ได้และพยายามใช้งาน IPv6 ในการติดต่อกับเครื่องที่ให้บริการปลายทาง เครื่องที่ให้บริการปลายทาง ตรวจสอบแล้วไม่พบว่า หมายเลข IP address นี้อยู่ในรายการของหมายเลข IP ที่อนุญาตให้เข้าถึงข้อมูลได้ ก็เลยปฏิเสธการเข้าถึงข้อมูล

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

    วันนี้ (2016-07-07)
    p2
    คุณสงกรานต์ และ หอสมุดคุณหญิงหลงประกาศผ่านกลุ่มของ facebook ว่าสามารถใช้งานบริการของ IEEE ได้แล้วทั้ง IPv4 และ IPv6

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

    ถ้าใช้งานไม่ได้ และ เข้าใจ และ สามารถช่วยตรวจสอบให้ได้ว่าขณะนั้นใช้โปรโตคอลใดที่ใช้งานไม่ได้ และ ถ้าเปลี่ยนเป็นอีกโปรโตคอลหนึ่ง สามารถใช้งานได้หรือไม่ … ถ้าทำได้อย่างนั้น ก็จะเป็นการช่วยเหลือผู้ดูแลเครือข่ายเป็นอย่างยิ่ง สมควรที่ได้รับคำขอบคุณและยกย่องจาก sysadmin/netadmin

    ถ้าผู้ใช้งาน ใช้งานไม่ได้ ก็ควรเป็นหน้าที่ของ sysadmin/netadmin ของหน่วยงานนั้นๆ เป็นผู้ตรวจสอบและวิเคราะห์ว่าปัญหาเกิดขึ้นจากอะไร การปล่อยให้ผู้ใช้งาน ซึ่งส่วนใหญ่อาจจะคุ้นเคยแค่การใช้งานแอพลิเคชั่นโดยทั่วไป ต้องมายุ่งเกี่ยวกับ enable/disable v4 protocol ซึ่งจะต้องแก้ไข registry ของระบบ (ภายใต้ข้อสมมติฐานที่ว่า ผู้ใช้ส่วนใหญ่ใช่ Windows) เป็นเรื่องที่ อาจจะผลักภาระให้กับผู้ใช้งานมากเกินไป และ ถึงแม้ผู้ใช้จะยินดีทำ แต่ข้อผิดพลาดที่อาจจะเกิดขึ้นได้ จะส่งผลที่ทำให้เกิดปัญหาที่ยากต่อการตรวจสอบในภายหลัง ได้มากกว่าครับ

    โอเค คราวนี้กลับมาที่ sysadmin/netadmin ผมคิดว่า การจัดการ disable/enable IPv6/IPv4 protocol โดยเข้าไปยุ่งเกี่ยวกับ registry ของ Windows ไม่น่าจะเป็นปัญหาอะไรสำหรับ ผู้ดูแลระบบ ที่ต้องเผชิญหน้ากับปัญหาในลักษณะนี้เป็นปกติอยู่แล้ว แต่ในนามของผู้ใช้ Linux ซึ่งไม่มีความสามารถในการเข้าถึง registry ของ Windows ผมคิดว่ามีเครื่องมือ ซึ่ง สามารถเรียกใช้งานได้จาก command line ของ Windows เองได้ โดยไม่จำเป็นที่จะต้องไปแก้ไข Windows Registry และสามารถนำมาใช้งานในการตรวจสอบการเข้าถึง IEEExplore สำหรับแต่ละโปรโตคอลได้

    เครื่องมือนั้นมี 2 ตัวครับ ก็คือ wget และ grep

    เครื่องมือทั้งสองนี้ ถือเป็นเครื่องมือพื้นฐานสำหรับ Linux Distribution หลักๆทั่วไป ที่จะติดตั้งมาให้แล้วสามารถเรียกใช้งานได้เลย โดยไม่จำเป็นจะต้องติดตั้งเพิ่ม ส่วน สำหรับ Windows ก็สามารถ Download ได้จาก

    wget — http://gnuwin32.sourceforge.net/packages/wget.htm
    grep — http://gnuwin32.sourceforge.net/packages/grep.htm

    ผมไม่สามารถตรวจสอบได้ว่า tools ทั้งสองตัวนี้ใช้งานได้จริงสำหรับ Windows ใหม่ๆหรือเปล่า (ตัว tools ทั้งสอง built ตั้งแต่ปี 2008) แต่จาก comment ของ Stack Overflow ที่นี่ ก็น่าพอเชื่อได้ว่าใช้งานได้

    การใช้งาน

    1. คำสั่ง wget มี option สำหรับบังคับให้ใช้ IPv4 (-4) หรือใช้ IPv6 (-6) สำหรับการติดต่อไปยัง web ปลายทาง
    2. ในหน้าแรกของ IEEExplore จะมีข้อความว่า “Prince of Songkla University provided by UniNet” อยู่ในหน้าแรกด้วย ถ้าหากว่าเครื่องคอมพิวเตอร์ที่ใช้ในการดาวน์โหลดใช้ IP ของมหาวิทยาลัย และ ทาง IEEExplore ได้ register หมายเลข IP นั้นเอาไว้แล้ว

    ดังนั้น เมื่อใช้คำสั่ง

    wget -q -O- -4 http://ieeexplore.ieee.org | grep "Prince of Songkla"
    

    หรือ

    wget -q -O- -6 http://ieeexplore.ieee.org | grep "Prince of Songkla"
    

    แล้วได้ข้อความว่า

    <h4>Prince of Songkla University provided by UniNet</h4>
    ก็แสดงว่า สำหรับ protocol นั้นๆสามารถใช้งานกับ IEEExplore ได้ ถ้าไม่มีข้อความใดๆ ก็แสดงว่ายังใช้งานไม่ได้ครับ

    หมายเหตุ: option “-O-” ของ wget จะทำให้ wget แสดงข้อมูลที่ download มาได้ออกทาง standard output ซึ่งในกรณีนี้ก็จะเป็นการส่งต่อให้กับคำสั่ง grep ผ่านทาง pipe “|” ส่วน option “-q” (quiet) ไม่ให้มันแสดง message แสดงสถานะที่มันกำลังติดต่อว่ากำลังทำอะไร และ ดำเนินการไปถึงใหนแล้ว เพราะในกรณีนี้ เราสนใจเฉพาะข้อมูลที่จะ download มาจากเครื่องที่ให้บริการเท่านั้น
    ถ้าอยากจะรู้ว่า ในการติดต่อไปยัง IEEExplore ครั้งนั้นๆ เครื่องของเราใช้หมายเลข IP ใดก็สามารถตรวจสอบ โดยใช้คำสั่ง

    wget -q -O- -4 http://ieeexplore.ieee.org | grep geoip
    wget -q -O- -6 http://ieeexplore.ieee.org | grep geoip
    

    และ ถ้าอยากจะรู้ว่าปกติแล้ว ถ้าไม่มีการระบุโปรโตคอล เครื่องของเราจะใช้ IPv4 หรือ IPv6 ในการติดต่อไปยัง IEEExplore ก็ให้ใช้คำสั่ง

    wget -q -O- http://ieeexplore.ieee.org | grep geoip
    

    ครับ ถ้าไม่ระบุ protocol ใน option คำสั่ง wget ก็จะใช้ค่าที่กำหนดโดยระบบปฏิบัติการ ว่าจะให้ใช้ protocol ใดก่อนครับ

  • Spam 2016-07-05

    หากท่านได้รับ Email ลักษณะเช่นนี้

    2559-07-05 16_04_13-Mailwatch for Mailscanner - Message Viewer

    เมื่อคลิก Link อาจจะได้หน้าตาอย่างนี้

    2559-07-05 16_04_53-Authenticate!

    นี่เป็น Email หลอกลวงครับ

  • ASP.NET Core Part I

    asp.net core คือ cross-platform framework สำหรับการพัฒนา web application ที่ทำงานบน .net core หรือ  full .net framework เดิม ( .net core สามารถใช้งานได้ทั้ง Windows , Linux และ MacOS โดยที่ส่วนประกอบต่างๆของ .net core ไม่ว่าจะเป็น runtime, libraries, compiler, language และเครื่องมือต่างๆ เป็น open source ทั้งหมด )  ซึ่ง asp.net core ได้รับการออกแบบใหม่ให้มีประสิทธิภาพดีกว่า asp.net เดิมโดยแบ่งส่วนต่างๆออกเป็น module ย่อยเพื่อลด overhead ในการเริ่มต้นทำงาน ซึ่ง asp.net core ประกอบไปด้วยกลุ่มของ NuGet package แทนที่การใช้งาน System.Web.dll ใน asp.net เดิม ซึ่งผู้พัฒนาสามารถเลือกเฉพาะ package ที่ต้องใช้งานเท่านั้น ทำให้ application มีขนาดเล็กลง มีประสิทธิภาพเพิ่มขึ้น,การพัฒนา Web UI และ Web API จะใช้ libraries เดียวกัน, สนับสนุนการใช้งาน dependency injection, web application สามารถใช้งานบน IIS หรือ self-host ภายใต้ process ของตัวเอง

    ในการพัฒนา asp.net core เราสามารถใช้เครื่องมือที่เป็น text editor ธรรมดาหรือจะใช้เครื่องมือช่วยในการพัฒนาอย่างเช่น Visual Studio ก็ได้ ในส่วนของโครงสร้างของ project asp.net core จะเปลี่ยนไปจากเดิม โดยการกำหนดค่า config ของ project สามารถกำหนดได้ที่ project.json

    {
     "title": "asp.net.core",
     "version": "1.0.0",
    
     "dependencies": {
       "NETStandard.Library": "1.6.0",
       "Newtonsoft.Json": "9.0.1"
     },
    
     "frameworks": {
       "netstandard1.6": {
          "imports": "dnxcore50"
        }
      }
    }

    การ reference ไปยัง NuGet package ที่ต้องการใช้งานใน project สามารถกำหนดได้ใน project.json โดยพิมพ์ชื่อ NuGet package ที่ต้องการพร้อมทั้งระบุ vesrion ในส่วน “dependencies” ซึ่งเมื่อทำการบันทึก project.json เครื่องมืออย่างเช่น visual studio จะทำการ restroe NuGet package ให้กับ project โดยอัตโนมัติ

    asp.net core ได้รับการออกแบบให้รองรับ client-side framework ต่างๆเช่น AngularJS หรือ bootstrap โดยใช้เครื่องมือที่เป็น package manager ในติดตั้ง client-side package ที่ต้องการใช้งาน อย่างเช่น Bower ที่จะกำหนด package ที่ต้องการใช้งานใน bower.json

    {
     "name": "asp.net",
     "private": true,
     "dependencies": {
       "bootstrap": "3.3.6",
       "jquery": "2.2.0",
       "jquery-validation": "1.14.0",
       "jquery-validation-unobtrusive": "3.2.6"
     }
    }

    หรือ npm ที่จะกำหนด package ที่ต้องการใช้งานใน package.json

    {
     "name": "asp.net",
     "version": "1.0.0",
     "private": true,
     "devDependencies": {
       "gulp": "3.8.11",
       "gulp-concat": "2.5.2",
       "gulp-cssmin": "0.1.7",
       "gulp-uglify": "1.2.0",
       "rimraf": "2.2.8",
       "typings": "1.0.5"
     },
     "dependencies": {
       "core-js": "^2.4.0",
       "reflect-metadata": "^0.1.3",
       "rxjs": "5.0.0-beta.6",
       "systemjs": "0.19.27",
       "zone.js": "^0.6.12"
     }
    }

    โดยเมื่อทำการบันทึก package manager จะทำการ restore package ที่ระบุ (bower.json หรือ package.json) ให้กับ project โดยอัตโนมัติ โดยที่ Bower จะติดตั้งลงใน /wwwroot/lib ในขณะที่ npm จะติดตั้งลงไปที่ folder /node_modules

    ในส่วนของ web root ของ asp.net core project จะอยู่ที่ folder /wwwroot ซึ่งต่างจาก asp.net เดิมที่ใช้ root folder ของ project เป็น web root โดยที่ /wwwroot จะเป็น folder ที่เก็บพวก static resources ต่างๆเช่น css, js และ image files

    entry point สำหรับ asp.net core application จะอยู่ที่ class “Startup” ซึ่งจะเป็น class ที่ใช้ในการกำหนด configuration และ service ต่างๆที่จะใช้ใน application โดย asp.net จะทำการค้นหา class ที่มีชื่อ startup ใน primary assembly (ในทุก namespace และไม่สนใจว่า class Startup จะเป็น public class หรือไม่ก็ตาม) ใน class Startup จะต้องมี method “Configure” ซึ่ง asp.net จะเรียกใช้งานตอนเริ่มต้น application (สำหรับ method “ConfigureServices” จะมีหรือไม่ก็ได้)

    สำหรับ Configure method จะต้องรับ parameter type “IApplicationBuilder” และอาจจะระบุ service ที่ต้องการใช้งานเช่น IHostingEnvironment และ ILoggerFactory ซึ่ง service เหล่านี้จะถูก inject โดย server โดยอัตโนมัติ

    IApplicationBuilder ถูกใช้ในการสร้าง application request pipeline ซึ่งสามารถเข้าถึงได้ผ่านทาง Configure method ใน Startup เท่านั้น

    IHostingEnvironment จะใช้เพื่อเข้าถึงข้อมูลสภาพแวดล้อมของ application เช่น EnvironmentName, ContentRootPath, WebRootPath และ web root file provider

    ILoggerFactory ให้ความสามารถในการทำ logging ซึ่งสามารถเข้าถึงได้ผ่านทาง Startup constructor และ Configure method ใน Startup เท่านั้น

     public void Configure(IApplicationBuilder app, 
                           IHostingEnvironment env,
                           ILoggerFactory loggerFactory)
     {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();
    
        if (env.IsDevelopment())
        {
          app.UseDeveloperExceptionPage();
          app.UseDatabaseErrorPage();
          app.UseBrowserLink();
        }
        else
        {
          app.UseExceptionHandler("/Home/Error");
        }
    
        app.UseStaticFiles();
    
        app.UseMvc(routes =>
        {
           routes.MapRoute(
           name: "default",
           template: "{controller=Home}/{action=Index}/{id?}");
         });
    }

    จะเห็นว่ามีการใช้ “Use” extension method เพื่อเพิ่ม middleware เข้าไปสู่ request pipeline ของ asp.net ตัวอย่างเช่น “UseMvc” extension method จะเป็นการเพิ่ม routing middleware เข้าไปสู่ request pipeline

    ใน part I นี้ได้กล่าวถึงส่วนหลักๆของ asp.net core (asp.net 5)  ที่เปลี่ยนไปจาก asp.net เดิม ทั้งในส่วนของ framework และการรองรับการพัฒนา client-side ในส่วนต่อไปเราจะเริ่มต้นพัฒนา asp.net core โดยการสร้าง asp.net core web application project ในแบบง่ายๆ

    อ้างอิง : https://docs.asp.net