Nine MVP's Blog

22/04/2010

ORM Series : Introduce NHibernate

Filed under: ORM — Nine MVP @ 2:27 am

 

  1. ORM Series : Start to ORM World
  2. ORM Series : Introduce to NHibernate
  3. ORM Series : Introduce Entity Framework   next…

Programming Level

  •     Intermediate (ควรมีประสบการณ์เขียนโปรแกรมด้าน OOP, ADO.NET และ SQL )

Required Development Tools and Libraries

  1. Visual Studio 2010 all edition or later
  2. C# 3.0 feature
  3. SQL Server 2005 or later
  4. NHibernate 2.1.2 GA  <- click download

 

Introduce NHibernate

ORM ตัวนี้ผมได้ศึกษามาระยะนึงตั้งแต่ v1.0 จนปัจจุบันมาถึง v2.1.2 กันแล้ว ซึ่ง version นี่เองที่เราจะมาพูดกัน บทความตอนนี้จะเป็นการแนะนำเจ้า NHibernate ว่าคืออะไร มีกลไกการทำงานอย่างไร และวิธีการใช้งานในเบื้องต้น หากใครอยากอ่านประวัติความเป็นมาก็เข้าไปดูได้ที่นี่ครับ  nhibernate history

Figure 1.  Application 3 Layers with NHibernate

จากรูปด้านบนนั่นคือการทำ Architectural Layering ของ Software จะเห็นได้ว่ามีสัดส่วนพื้นฐานง่าย ๆ เป็น 3 ส่วนคือ

  1. Presentation Layer  โค้ดส่วนที่เกี่ยวข้องกับ User Interface ไม่ว่าจะตรวจสอบค่า จัดรูปแบบ ต่าง ๆ จะอยู่ที่ชั้นนี้ทั้งหมด
  2. Business Logic Layer  โค้ดส่วนที่เกี่ยวข้องกับ Business ต่าง ๆ ของระบบเช่น คำนวนค่าต่าง ๆ  การหายอด การขอดูรายการในระบบ และเป็นชั้นที่จัดเก็บ Business Objects ต่าง ๆ ด้วย 
  3. Data Access Layer  โค้ดส่วนที่ใช้จัดการ object ทั้ง Insert/ Delete/Update/Select ลง Database

และ กล่องแดง ๆ นั่นคือ Object Relational Mapping Framework ที่ชื่อ NHibernate ที่เราจะมาทำความรู้จักกันแบบเจาะโครงสร้าง ลงรายละเอียดการทำงานแต่ละส่วนกันให้เข้าใจ ตัวของ NHibernate เองก็จะเกี่ยวข้องอยู่กับ Data Access Layer โดยเราจะเรียกใช้ NHibernate จากใน DAL     ซึ่ง DAL อาจจะ implement interface เอาไว้ ให้ business เรียกใช้ก็ได้ช่วยได้การ decouple layer ได้สมบูรณ์ขึ้น

NHibernate Concept and Architecture

Figure 3. NHibernate Concept Overview

NHibernate จะทำหน้าที่เพียงเปลี่ยนลักษณะของ Objects <-ไปกลับ-> Database Recode ให้เรานั้นเอง       แนวคิดและวิธีการของ NHibernate ในการทำ mapping object เข้ากับ table ใน database จะใช้ XML Mapping, Attribute หรือ utility อย่าง Fluent NHibernate ก็ได้ (บทความนี้สอน XML Mapping)       โดยเราจะต้องตั้งค่าระบุว่า Class ใน Domain Object นี้จะไป Map เข้ากับ Table ไหน และ Property นี้จะไป map เข้ากับ Column ไหนใน Table รวมไปถึงการกำหนด property เพิ่มเติมได้ค่อนข้างยืดหยุ่นทีเดียว แต่ปัจจุบันยังไม่มี GUI Tool ให้เราใช้ จึงค่อนข้างจะต้องใช้ความรู้ในการสร้าง Mapping เช่นกัน

ต่อมาคือ Detail Architecture ของ NHibernate ดังรูปข้างล่างนี้

Figure 4. NHibernate Architecture

จากรูปด้านบนผมจะแนะนำ NHibernate Components ที่เราต้องรู้จักกันก่อนครับ (reference nhibernate document 2.0) โดยขอแนะนำที่จำเป็นสำหรับเริ่มต้นเรียนู้ไว้เพียงแค่นี้ก่อนครับ

  1. SessionFactory (NHibernate.ISessionFactory) เป็นอ็อปเจ็กที่ใช้เริ่มต้นการทำงานของ NHibernate โดยจะ load mapping file และ config ต่าง ๆ เข้ามาตั้งต้นใช้งาน อีกทั้งยังเป็น factory สำหรับสร้าง ISession ซึ่งอาจจะมีแคชของข้อมูล ในกรณีที่มีนำข้อมูลกลับมาใช้งานในระดับของ transactions, process หรือ cluster-level.

  2. Session (NHibernate.ISession) เป็นอ๊อปเจ็กที่ทำงานแบบเธรดเดี่ยว(Single Thread) มีช่วงการทำงานที่สั้น ซึ่งจะเป็นตัวที่ใช้ติดต่อระหว่าง application กับส่วนเก็บข้อมูลของระบบเช่น database เป็นต้น  โดยการทำงานนั้นจะเป็นการใช้งาน ADO.NET ในการติดต่อนั้นเอง ตลอดจนยังเป็น Factory ไว้สร้าง ITransaction เมื่อต้องการใช้งาน transaction  ที่สำคัญยังมีการใช้ Cache กับ Persistant Object ด้วย ช่วยให้เราสามารถทำงานกับ object graph และกรณีค้นหา object จาก ID เป็นต้น

  3. Persistent Objects and Collections : เป็นอ๊อปเจ็กที่มีช่วงชีวิตสั้น ๆ โดยเป็นการทำงานของเธรดเดี่ยว(Single Thread) โดยจะเก็บค่า persistent state เอาไว้ด้วย และอาจจะรวมไปถึง business method บางตัวไว้ด้วย ซึ่งก็แล้วแต่ Design ของแต่ละคน    ซึ่งอ๊อปเจ็กตัวนี้จะเป็นพิมพ์เดียวกับ Domain Model ที่ออกแบบไว้ โดยจะคงคุณสมบัติของ POCO ไว้ได้  และที่สำคัญอ๊อปเจ็กตัวนี้จะอยู่ใน Session ของ ISession  และหาก Session ดังกล่าวปิดลง อ๊อปเจ็กเหล่านี้จะลอยตัวจาก nhibernate และส่งต่อไปยัง layer อื่น ๆ ได้ (โดยอาจจะ map object ไปเป็น dto เพื่อส่งต่อไป presentation layer ก็ได้)

  4. Transient Objects and Collections : คือ อ๊อปเจ็กที่อยู่ใน system memory โดยเป็นอ๊อปเจ็กที่ถูกสร้างขึ้นใหม่ หรือเป็นอ๊อปเจ็กที่ไม่ได้อยู่ในการดูแลของ ISession  

 

ดาวน์โหลดและติดตั้ง NHibernate และ Fluent NHibernate

  1. ทำการดาวน์โหลด NHibernate 2.1.2 GA (<— กดเลย)
  2. แตกzip ไว้ใน C:\NHibernate\NHibernate-2.1.2.GA-bin 

 

ตั้งค่าให้ Visual Studio ใช้งาน NHibernate XML Intellisense

เนื่องจากการพิมพ์ xml configuration ของ nhibernate เองใน visual studio เองนั้น มีโอกาสผิดพลาดสูงมาก intellisense นี้จะช่วยลดความผิดพลาดในการทำงานครับ มี step ดังนี้

  1. หลังจากที่ download NHibernate มาแล้วให้ unzip และเข้าไปใน folder NHibernate-2.1.2.GA-bin\Required_Bins เลือก copy file nhibernate-configuration.xsd และ nhibernate-mapping.xsd
  2. จากนั้นนำไปวางใน visual studio ตาม path ดังนี้ “C:\Program Files\Microsoft Visual Studio X.0\xml\Schemas”
  3. จบขั้นตอน

 

มาสร้างโปรเจ็คแรกกัน First Application with NHibernate

เราจะใช้งานเจ้า NHibernate กับตัวอย่าง Application ง่าย ๆ กันครับ โดยเราจะสร้าง Data Access Layer สำหรับ Customer Profile ซึ่งจะมีไดอะแกรมต่าง ๆ เป็นโมเดลดังนี้

1. Business Domain Class Diagram

Figure 5. Customer Profile Class Diagram

2. Database: Tables Structure

Figure 6. Customer Profile Database Model

หลังจากที่ได้ดู Class Diagram และ Database Diagram ทั้ง 2 ไดอะแกรมไปแล้วเราก็จะมาทำการสร้างงานโดยใช้ Visual Studio กัน

สร้าง Database

1. สร้าง database ชื่อ CustomerDB

2. ทำการสร้างเทเบิ้ลด้วย script ล่างนี้

USE [CustomerDB]
GO

CREATE TABLE [dbo].[Customer](
    [Id] [uniqueidentifier] NOT NULL,
    [FirstName] [nvarchar](50) NULL,
    [LastName] [nvarchar](50) NULL,
    [Age] [int] NULL,
    [Sex] [char](5) NULL,
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Address](
    [Id] [uniqueidentifier] NOT NULL,
    [Road] [nvarchar](255) NOT NULL,
    [City] [nvarchar](255) NOT NULL,
    [Country] [nvarchar](100) NOT NULL,
    [PostCode] [char](5) NOT NULL,
    [Owner_Id] [uniqueidentifier] NULL,
CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Address]  WITH CHECK ADD  CONSTRAINT [FK_Address_Customer] FOREIGN KEY([Owner_Id])
REFERENCES [dbo].[Customer] ([Id])
GO
ALTER TABLE [dbo].[Address] CHECK CONSTRAINT [FK_Address_Customer]
GO

 

 

เริ่มสร้างโปรแกรม

มีขั้นตอนดังนี้

1. สร้างโปรเจ็คไฟล์

1.1  ไปที่ Menu –> File –> New –> Project… –> จากนั้นเลือก Visual C# –> .NET Framework 3.5 –> Class Library –> ใส่ค่า Name:= Vol1.Sample01.MyDAL, Location:= c:\ORMSeries, Solution name:= ORMSeries –>  กด OK

1.2 จะได้โปรเจ็คที่มีโครงสร้างดังภาพด้านล่างนี้

และให้ลบ Class1.cs ทิ้ง

 

2. เรียกใช้ NHibernate library

2.1 เรียกใช้ NHibernate คลิ๊กขวาที่ Vol1.Sample01.MyDal Project –> เลือก add reference… –> browse ไปที่ “C:\NHibernate\NHibernate-2.1.2.GA-bin\Required_Bins” –> เลือก NHibernate.dll กด OK

       

2.2 เรียกใช้ Dynamic Proxy Library คลิ๊กขวาที่ Vol1.Sample01.MyDal Project –> เลือก add reference… –> browse ไปที่ “C:\NHibernate\NHibernate-2.1.2.GA-bin\Required_For_LazyLoading\Spring” –> เลือก NHibernate.ByteCode.Spring.dll กด OK

2.3 มาตรวจสอบ Library ใน Reference กันครับ

 

3. สร้าง Entity Class

3.1 สร้างโฟลเดอร์ โดยคลิ๊กขวาที่โปรเจ็ค –> Add –> New Folder ตั้งชื่อว่า “DomainEntities”

3.1 สร้าง Customer Class –> คลิ๊กขวาที่โฟลเดอร์ “DomainEntities” –> Add –> Class… –> ตั้งชื่อว่า  “Customer.cs”  และ copy code ด้านล่างไปแปะ

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Vol1.Sample01.MyDAL.DomainEntities
{
    public class Customer
    {
        public virtual Guid Id { get; private set; }
        public virtual string FirstName { get; set; }
        public virtual string LastName { get; set; }
        public virtual int Age { get; set; }
        public virtual Sex Sex { get; set; }
        public virtual IList<Address> Addresses { get; set; }

        public Customer()
        {
            Addresses = new List<Address>();
        }
    }

    public enum Sex
    {
        Male, Female
    }
}

 

3.2 สร้าง Address Class –> คลิ๊กขวาที่โฟลเดอร์ “DomainEntities” –> Add –> Class… –> ตั้งชื่อว่า  “Address.cs”  และ copy code ในตารางด้านล่างไปแปะ

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Vol1.Sample01.MyDAL.DomainEntities
{
    public class Address
    {
        public virtual Guid Id { get; private set; }
        public virtual string Road { get; set; }
        public virtual string City { get; set; }
        public virtual string Country { get; set; }
        public virtual string PostCode { get; set; }

        public Address()
        {
        }

    }
}

 

4. สร้าง Mapping File ใช้สำหรับบอก NHibernate ว่า assembly file –>Class–>Property ใด map เข้ากับ Database –>Table –> Colume ใดบ้าง

     4.1  สร้าง mapping สำหรับ Customer Class: คลิ๊กขวาที่โฟลเดอร์ “DomainEntities” –> Add –> New Item… –> Xml File  –> ตั้งชื่อว่า  “Customer.hbm.xml” –> คลิ๊ก Add

       

     จากนั้นและ copy xml code ในตารางด้านล่างไปแปะ และทำการ Save

 

<?xml version="1.0" encoding="utf-8" ?>
<!–  เริ่มต้นสร้าง mapping  พร้อมระบุ assembly name ของ class ที่บรรจุอยู่ภายใน   และระบุความลึกของ namespace ไปถึงตำแหน่งที่ class อยู่  –>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Vol1.Sample01.MyDAL"
                   namespace="Vol1.Sample01.MyDAL.DomainEntities" >

  <!–  เริ่ม map class พร้อมระบุ table ที่จะ map เข้าด้วยกัน  –>
  <class name="Customer" table="Customer">

    <!– กำหนด id ของ class map เข้ากับ Pk ของ column –>
    <id name="Id" column="Id">
      <!– ระบุให้ NHibernate ทำการ auto assign Guid ให้กับ Property นี้ –>
      <generator class="guid"/>     
    </id>
    <!– เนื่องจากชื่อ property เหมือนกับ column ใน DB จึงไม่ต้องระบุ column name –>
    <property name="FirstName" column="FirstName"/>  
    <property name="LastName" />
    <property name="Age" />
    <property name="Sex"  />
     <!–bag คือ collection object มีมากกว่า 1 ซึ่งเป็นลักษณะ 1:M ซึ่ง customer สามารถมี address
    ได้มากกว่า 1 และกำหนดให้ collection type เป็น generic–>
    <bag name="Addresses"  generic="true" cascade="all" >
       <!–ระบุ colume FK name ของ table address–>
      <key column="Owner_Id" not-null="true" foreign-key="Id"/>
       <!–ระบุ class name ที่จะดึงข้อมูลมาใส่ collection–>
      <one-to-many class="Address"/>
    </bag>
  </class>
</hibernate-mapping>

 

4.2  สร้าง mapping สำหรับ Address Class: คลิ๊กขวาที่โฟลเดอร์ “DomainEntities” –> Add –> New Item… –> Xml File  –> ตั้งชื่อว่า  “Address.hbm.xml” –> คลิ๊ก Add

 

   

และ copy xml code ด้านล่างไปแปะ

<?xml version="1.0" encoding="utf-8" ?>
<!–  เริ่มต้นสร้าง mapping  พร้อมระบุ assembly name ของ class ที่บรรจุอยู่ภายใน   และระบุความลึกของ namespace ไปถึงตำแหน่งที่ class อยู่  –>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Vol1.Sample01.MyDAL"
                   namespace="Vol1.Sample01.MyDAL.DomainEntities" >
  <!–  เริ่ม map class พร้อมระบุ table ที่จะ map เข้าด้วยกัน  –>
  <class name="Address" table="Address">

    <!– กำหนด id ของ class map เข้ากับ Pk ของ column –>
    <id name="Id" column="Id">
      <!– ระบุให้ NHibernate ทำการ auto assign Guid ให้กับ Property นี้ –>
      <generator class="guid"/>
    </id>

    <!– เนื่องจากชื่อ property เหมือนกับ column ใน DB จึงไม่ต้องระบุ column name ก็ได้ –>
    <property name="Road" column="Road"/>
    <property name="City" />
    <property name="Country" />
    <property name="PostCode" />
  </class>
</hibernate-mapping>

 

 

4.3  จะได้ output file ตามรูปด้านล่างนี้

 

และใน Solution Explorer ให้ทำการคลิ๊กเลือก Customer.hbm.xml และไปปรับค่าที่ Property windows แก้ไขค่า Build Action = Embeded Resource ตามรูปด้านล่าง

ทำซ้ำกับ file Address.hbm.xml เช่นเดียวกัน

 

 

 

5. สร้าง Config file สำหรับการตั้งค่าการทำงานของ NHibernate ทั้งหมด

5.1  Solution Explorer คลิ๊กขวาที่ Vol1.Sample01.MyDAL –> เลือก Add –> New Item… –> XML File –> ตั้งชื่อว่า “hibernate.cfg.xml” –> คลิ๊ก Add  จากนั้น copy code ในตารางด้านล่างไปแปะ และทำการบันทุึก

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <!– สร้าง session factory –>
  <session-factory name="Vol1.Sample01.MyDAL">
    <!– cache provider เป็นการระบุให้ nh ใช้ cache –>
    <property name="cache.provider_class">NHibernate.Cache.HashtableCacheProvider, NHibernate</property>
    <!– กำหนดให้ใช้ cache ของ query  –>
    <property name="cache.use_query_cache">true</property>
    <!– ไม่ใช้การตรวจสอบในตอนสร้าง session –>
    <property name="query.startup_check">false</property>

    <!– จำนวน batch ในการทำงาน –>
    <property name="adonet.batch_size">10</property>
    <!– กำหนด transaction level –>
    <property name="connection.isolation">ReadCommitted</property>

    <!– กำหนดให้ gen "" ครอบ sql ที่เป็น keyword ป้องกัน error –>
    <property name="hbm2ddl.keywords">auto-quote</property>
    <!– กำหนดให้ show sql ที่ gen ได้ ที่ console log –>
    <property name="show_sql">false</property>
    <!– กำหนดให้ format sql ให้อ่านง่าย เว้นบรรทัด ที่ console log–>
    <property name="format_sql">true</property>

    <!– กำหนด driver สำหรับติดต่อ dabase  –>
    <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <!– กำหนดตัวแปลง sql สำหรับ database  –>
    <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
    <property name="connection.connection_string">Server=.;initial catalog=CustomerDB;Integrated Security=SSPI</property>

    <property name="use_outer_join">true</property>
    <property name="command_timeout">444</property>
    <property name="query.substitutions">true 1, false 0, yes ‘Y’, no ‘N'</property>
    <property name="adonet.wrap_result_sets">false</property>
    <!– กำหนด DI สำหรับสร้าง proxy class ปกติเดิม NH จะใช้ castle แต่สำหรับ v2.1.x นั้น มีให้เลือกใช้ Spring.Net, Castle, Linfu –>
    <property name="proxyfactory.factory_class">NHibernate.ByteCode.Spring.ProxyFactoryFactory, NHibernate.ByteCode.Spring</property>

    <!– !!!!!!!!!  กำหนด assembly name ที่ต้องการจะใช้ NH ทำการ load เข้ามาทำงาน    !!!!!!!!!! –>
    <mapping assembly="Vol1.Sample01.MyDAL"/>
  </session-factory>
</hibernate-configuration>

 

 

5.2 บังคับ Client Project ให้เอา config file ของ NH ไปใช้งานด้วย  โดยไปที่ Solution Explorer เลือก hibernate.cfg.xml –> เลื่อนไปดูที่ Properties window ปรับค่า Build Action = Content และ Copy to Output Deirectory = Copy always

 

 

6. สร้าง Helper เพื่อไว้เรียกใช้ Session ของ NH ได้สะดวกขึ้น (ตัวอย่างแบบง่าย สำหรับ Client App)

6.1  ไปที่ Solution Explorer เลือก Vol1.Sample01.MyDAL คลิ๊กขวาเลือก –> Add –> Class..  ตั้งชื่อว่า “NHibernateHelper.cs” ให้ Copy code จากด้านล่างนี้แปะ และทำการ save

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using NHibernate;
using NHibernate.Cfg;

namespace Vol1.Sample01.MyDAL
{
    /// <summary>
    /// Helper นี้เหมาะสำหรับ basic client application (ไม่เหมาะกับ web app)
    /// </summary>

    public static class NHibernateHelper
    {
        // กำหนดตัวแปร factory ไว้เป็น static เมื่อสร้างขึ้นใช้งานใน App ไม่ต้องสร้างใหม่ทุกครั้งเนื่องจาก จะใช้เวลาในการสร้างนานมาก
        private static readonly ISessionFactory sessionFactory;
        // สร้าง Session
        private static ISession currentSession;

        static NHibernateHelper()
        {
            // ทำการสร้าง factory
            sessionFactory = new Configuration().Configure().BuildSessionFactory();
        }

        // เปิด session เพื่อทำงานกับ DB
        public static ISession GetCurrentSession()
        {
            if (currentSession == null)
            {
                // เปิด session ใหม่
                currentSession = sessionFactory.OpenSession();
            }
            return currentSession;
        }

        // ทำการปิด session คล้ายการปิด db connection
        public static void CloseSession()
        {
            if (sessionFactory == null)
            {
                return;
            }
            currentSession.Close();
        }

        // ปิด factory ยกเลิกการใช้งาน
        public static void CloseSessionFactory()
        {
            if (sessionFactory != null)
            {
                sessionFactory.Close();
            }
        }
    }

}

 

7. สั่ง Build ด้วยการกด Ctrl + Shift + B  หรือไปที่ Menu –> Build –> Build Solution  เมื่อสำเร็จ จะได้ DAL โปรเจ็คที่มีรูปร่างหน้าต่างประมาณนี้

 

 

8.  นำ MyDAL ของเราไปใช้งาน

8.1 ทำการสร้าง Client Project  เริ่มต้นไปที่ Menu –> File –> Add –> New Project..   ตั้งชื่อว่า ClientTest  และกด Add

    

8.2 ทำการ Add Reference ของ NHibernate  ย้อนไปทำตามข้อ 2.1 และ 2.2

8.3 ทำการ Add Reference ของ Vol1.Sample01.MyDAL  โดยไปที่ Solution Explorer –> เลือก TestClient Project และทำตามรูปด้างล่าง

    

    

     จะได้ output ตามรูปนี้

      

 

8.4  เปิด Program.cs ขึ้นมาทำการเขียนโค้ดด้านล่างนี้

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClientTest
{
    class Program
    {
        static void Main(string[] args)
        {
           //// เปิด session เพื่อเตรียมทำงานกับ Database
            NHibernate.ISession session = Vol1.Sample01.MyDAL.NHibernateHelper.GetCurrentSession();
            // ใช้งาน transaction
            NHibernate.ITransaction tx = session.BeginTransaction();

           #region Save
            // ทำการสร้าง customer instance
            Vol1.Sample01.MyDAL.DomainEntities.Customer cust1 = new Vol1.Sample01.MyDAL.DomainEntities.Customer();
            cust1.FirstName = "Somchai";
            cust1.LastName = "Sakleoi";
            cust1.Sex = Vol1.Sample01.MyDAL.DomainEntities.Sex.Male;
            cust1.Age = 25;

            // ทำการสร้าง address ของ customer
            Vol1.Sample01.MyDAL.DomainEntities.Address addr = new Vol1.Sample01.MyDAL.DomainEntities.Address();
            addr.Road = "Ratchada";
            addr.City = "Huaykwang";
            addr.Country = "Thailand";
            addr.PostCode = "10310";

           // เพิ่ม address ให้ customer
            cust1.Addresses.Add(addr);

           // สั่ง Save ลง Database
            session.Save(cust1);
            #endregion

            #region Search
            // ทำการค้นหา customer object ใน table ด้วยเงื่อนไข firstname like ‘Som%’
            var res = session.CreateCriteria(typeof(Vol1.Sample01.MyDAL.DomainEntities.Customer))
                .Add(NHibernate.Criterion.Restrictions.Like("FirstName", "Som%")).List<Vol1.Sample01.MyDAL.DomainEntities.Customer>() ;

            Console.WriteLine(" Search customer by FirstName ‘Som%’ found {0} object ", res.Count);
            foreach (var customer in res)
            {
                Console.WriteLine("customer firstname={0} lastname={1}  have address {2} ", customer.FirstName,
                                  customer.LastName, customer.Addresses.Count);
            }
           #endregion

            #region Update
            var custx = res[0];
           // แก้ไขค่า firstname ของ custx
            custx.FirstName = "XXX";
            // สั่ง update custx ใน table
            session.Update(custx);
            Console.WriteLine("Update customer name from ‘{0}’ to ‘{1}’",res[0].FirstName, custx.FirstName);
           #endregion

            #region Delete
            //ลบ object custx ออกจาก table
            session.Delete(custx);
            Console.WriteLine("Delete customer name ‘{0}’ ", custx.FirstName);
            #endregion

            // สั่งให้ commit transaction
            tx.Commit();
            // สั่งปิด Session
            Vol1.Sample01.MyDAL.NHibernateHelper.CloseSession();

            Console.ReadKey();
        }
    }
}

 

8.5  เมื่อทำการกด Run โปรแกรมด้วยการกด F5 จะได้ output ตามรูปด้านล่าง

 

อธิบายการทำงานของ Code ด้านบน

จะเห็นได้ว่ามีการสร้าง customer และ address  และได้มีการสั่งให้ Save ซึ่ง NHibernate จะบันทึกทั้ง Customer , Address ลงเทเบิ้ล

           // สั่ง Save ลง Database
            session.Save(cust1);

จากนั้นก็ได้มีการ Search customer object ด้วยการกำหนดเงื่อนไข FirstName Like ‘Som%’  ซึ่งส่งค่ากลับมาเป็น List<Customer>

          // ทำการค้นหา customer object ใน table ด้วยเงื่อนไข firstname like ‘Som%’
           var res = session.CreateCriteria(typeof(Vol1.Sample01.MyDAL.DomainEntities.Customer))
                .Add(NHibernate.Criterion.Restrictions.Like("FirstName", "Som%")).List<Vol1.Sample01.MyDAL.DomainEntities.Customer>() ;

ต่อมาจะสั่งให้ update customer ที่ search มาได้

           // แก้ไขค่า firstname ของ custx
            custx.FirstName = "XXX";
            // สั่ง update custx ใน table
            session.Update(custx);

 

และสุดท้าย คำสั่ง Delete 

            //ลบ object custx ออกจาก table
            session.Delete(custx);

 

สรุปตอนท้าย

จะเห็นว่าการใช้งาน NHibernate ค่อนข้างจะมีขั้นตอนซับซ้อน ซึ่งนี่เป็นสิ่งที่ทาง Hibernate (java) เขาใช้งานกันมายาวนาน และขึ้นชื่อว่า Hibernate นั้นสร้างชื่อเสียงเป็นอย่างมาก   เพราะความยืดหยุ่นในการทำงานและประสิทธิภาพการทำงานนั้นจัดได้ว่าในระดับที่ดีและไว้ใจได้เนื่องจากใช้งานกันมายาวนาน  ยังรวมไปถึงเหล่า contributor ต่าง ๆ ที่คอยพัฒนาไลบราลี่ไว้เสริมการทำงานอื่นๆ ให้ NHibernate อีกมากมาย      ซึ่ง NHibernate ได้พัฒนาโดยอิงตาม Hibernate ทุกประการ     จากบทความนี้เป็นเพียงพื้นฐานเริ่มต้นเล็กน้อย  ก่อนจะต่อยอดไปศึกษาในเรื่องที่ซับซ้อนกว่านี้เช่น Mapping Pattern, Performance Tuning, Caching, Transaction และ การใช้งานร่วมกับ framework อื่น ๆ เช่น Spring.Net, AOP เป็นต้น 

ซึ่งในตอนต่อไปจะมาสอนการสร้าง Mapping ในรูปแบบต่างๆ ที่ซับซ้อนกว่านี้ด้วย Real World Business Domain

 


 

สามารถ download source code ได้ที่นี่

ORMSeries Code Sample Download Here!!

 

Chalermpon Areepong Nine (นาย)

Microsoft MVP Thailand ASP.NET

email : nine_biz-talk.net at hotmail dot com

11 Comments »

  1. เยี่ยม ครับ เยี่ยมยอด

    Comment by Teerapong S. — 02/01/2011 @ 8:55 pm

    • ขอบคุณครับ

      Comment by Nine MVP ASP.NET — 03/01/2011 @ 10:45 am

  2. […] ครับ สำหรับเรื่องของ NHibernate นั้นคงต้องว่ากันต่อไป นะครับส่วนท่าที่ต้องการจะอ่านเพิ่มเติมก็สามารถไปตาม link นี้นะครับ อ่านเพิ่มเติมได้ที่ […]

    Pingback by NHibernate Why ??? « Teerapong Sontayaman ‘s Kode Talker .NET — 11/01/2011 @ 4:44 pm

  3. เป็นบทความที่เยื่ยมยอดมากๆครับ แต่อยากให้ช่วยเสริมการใช้ Repository Pattern เพื่อนำมาต่อยอดในการ
    สร้าง Criteria และ OrderBy ผ่านคลาสให้ด้วยครับ (แบบไม่ใช้ SQL String ครับ)

    Comment by Huz — 25/01/2011 @ 9:28 am

    • ครับ จะรับไว้เพิ่มเติมในบทความต่อไปครับ

      Comment by Nine MVP ASP.NET — 25/01/2011 @ 9:54 am

  4. ขอบคุณครับ ตย. ดีมากเลยครับ (แต่ Comment tag ของ xml ไฟล์ผิดนิดหน่อยครับ)

    Comment by Jira — 15/02/2011 @ 7:54 pm

    • ผิดอะไรตรงไหนรบกวน ชี้จุดด้วยครับ ผมอาจจะตกหล่นที่ไหนไป จะได้แก้ไขได้ถูกต้อง

      Comment by Nine MVP ASP.NET — 15/02/2011 @ 10:06 pm

  5. ที่ xml ทุกไฟล์ที่ให้ copy เช่น

    แก้ไขเป็น

    ปล. ในไฟล์ Source code ที่ให้ download ถูกแล้ว แต่ถ้า Copy code ไปจะไม่ถูกครับ

    Comment by Jira — 17/02/2011 @ 1:46 pm

    • !– สร้าง session factory – เปลี่ยนเป็น !– สร้าง session factory —

      Comment by Jira — 17/02/2011 @ 1:51 pm

      • การแสดงผล Source code บนหน้า Web มันแสดงไม่ถูกต้องนี้เองมันแปลง comment tag เปลี่ยนไป Copy ไปแล้วมันเลยผิด (ระวังกันหน่อยละกันครับ)

        Comment by Jira — 17/02/2011 @ 1:56 pm

  6. Jira :

    ที่ xml ทุกไฟล์ที่ให้ copy เช่น

    แก้ไขเป็น

    ปล. ในไฟล์ Source code ที่ให้ download ถูกแล้ว แต่ถ้า Copy code ไปจะไม่ถูกครับ

    งั้นอาจจะต้อง download source code ไปรันเองเลยครับ ตัดปัญหาของ html encode ออกไป

    Comment by Nine MVP ASP.NET — 17/02/2011 @ 10:26 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: