เริ่มต้น SQLite กับ NHibernate… Actions!

เกริ่นนำ

สวัสดีครับ บทความนี้ผมจะแสดงขั้นตอนการพัฒนาการ persist domain model ที่มี relationship แบบ hierarchy และ one-to-many ไปยังฐานข้อมูล SQLite ที่มีลักษณะของ mobility  โดยใช้ NHibernate xml-mapping

ก่อนจะเริ่มกันแนะนำให้อ่าน NHibernate จากบทความ สร้าง mapping fluently Domain Model ด้วย Fluent NHibernate… Actions! ก่อนนะครับแล้ว donwload source code domain model นี้มาทำต่อในบทความนี้ เพราะผมจะแสดง xml mapping จาก domain model นั้นเลย ก่อนอื่นขอแนะนำให้รู้จัก SQLite กันก่อน เพราะผมไม่เคยเขียนถึงมันมากก่อนเลย

SQLite คืออะไร

SQLite คือ software library ที่สร้างขึ้น และประยุกต์แนวคิดมาจาก SQL database engine มันมีคุณลักษณะ Self-Contained, Serverless, Zero-Configuration และ Transactional ดังนี้

  • Self-Contained คือ SQLite ต้องการ การสนับสนุนจาก library อื่นหรือ operating system(OS) ใดๆน้อยมากๆ ดังนั้นเราจึงแค่ copy library ของ SQLite แล้ว config มันอีกเล็กน้อยเท่านั้น ในขั้นตอนการ deploy program
  • Serverless คือ โดยปกติ SQL database engine จะมี server process ที่แยกออกจาก  program ดังนั้น program เมื่อต้องการเข้าใช้ database จึงต้องมีการติดต่อสื่อสารโดยใช้ interprocess communication (ที่ใช้ปกติคือ TCP/IP) เพื่อส่ง request ไปยัง server แล้วรอผลกลับมา แต่ SQLite ไม่ทำงานแบบนั้น กระบวนการของ SQLite คือเมื่อ program ต้องการใช้ database มันจะ read/write กับ file database บน disk ของเครื่องที่มัน deploy อยู่แล้วโดยตรงได้เลย
  • Zero-Configuration คือ SQLite ไม่จำเป็นต้อง “installed” ก่อนใช้งาน ไม่จำเป็นต้องมีกระบวนการ “setup” SQLite Server ไม่จำเป็นต้องมีกระบวนการ started, stopped, หรือ configured มันใช้งานได้ทันทีเมื่อ program ต้องการ
  • Transactional คือ การทำงานกับ database ในหนึ่ง process ที่มีการใช้ข้อมูลใดๆ เมื่อมีการเปลี่ยนแปลงแล้ว และเมื่อสืบค้นขึ้นมาเมื่อไรก็แล้วแต่ มันจะต้องมีความเป็น Atomic, Consistent, Isolated, และ Durable (ACID)
    SQLite สร้างขึ้นและประยุกต์ serializable transactions นั่นคือมันจะยังคงไว้ซึ่งความเป็น atomic, consistent, isolated, และ durable ถ้าเกิดเหตุการณ์ที่ transaction ถูกขัดจังหวะโดย
    program crash หรือ operating system crash หรือ  power ของ computer เกิดข้อผิดพลาดขึ้น

ซึ่งผมเองคิดว่ามันสำคัญมากกับ Software  Architecture ที่เป็น Agent-based มี communication แบบ Event-based ทำงานอยู่บน infrastructure แบบ Ubiquitous computing มันเป็นแนวคิดที่เจ๋งมากๆ หากจะนำเอา SQLite มาใช้เป็น persist state ของ Agent ของผม

หรือจะนำ SQLite มาใช้กับ application ในแบบ hibrid คือสามารถทำงานได้แม้ว่าจะเกิดอะไรขึ้นกับระบบเครือข่าย หรือ server database หรือนำมาประยุกต์ใช้กับการทำ Mockup ก็ยอดเยี่ยมเลยทีเดียวครับ  😉

Download และติดตั้ง SQLite

1. download SQLite สำหรับ .NET จาก http://sourceforge.net/projects/sqlite-dotnet2/develop และทำการติดตั้ง

2. download เครื่องมือ SQLite Administrator สำหรับเปิดดู เพื่อจัดการ file SQLite database จาก http://sqliteadmin.orbmu2k.de/ และทำการติดตั้ง

หลังจาก download และ ติดตั้ง SQLite เสร็จแล้วเราก็มาเริ่มใช้งานมันกันเลย

สร้าง NHibernate  XML-Mappings… Actions!

1. สร้าง NHibernate  XML-mappings จาก domain model ที่ได้สร้างไว้แล้ว โดยเปิด visual studio 2010 ขึ้นมา แล้วสร้าง projects ใหม่ในแบบ class library ตั้งชื่อว่า Infrastructure.Orm.NHibernateMappings

2. สร้าง mapping model Product, Book, Movie และ ActorRule จาก projects Enterprise.Domains ที่ download มาแล้วข้างต้น

  1. ใน Solution Explorer window right-click บน project ของคุณ และ Add | New Item
  2. เลือก category Data ที่อยู่ทางด้านซ้ายของ dialog Add | New Item
  3. เลื่อก XML File ที่อยู่ทางด้านขวาของ dialog Add | New Item
  4. ตั้งชื่อ file Name ในรูปแบบ <ClassName>.hbm.xml เช่น Product.hbm.xml, Book.hbm.xml
  5. ใน Solution Explorer, right-click ที่ <ClassName>.hbm.xml  และเลือก Properties แล้วเปลี่ยน Build Action จาก Content ไปเป็น Embedded Resource
  6. กลับไปทำซ้ำข้อ 1 จนครบทุก domain model ใน Enterprise.Domains ครับ

3. สรุป file NHibernate XML-mapping ทั้งหมดได้ตามภาพนี้

สร้าง Unit test projects และ setup library ให้พร้อม… Actions!

1. ใน Solution Explorer window right-click บน project ของคุณ และ Add | New Projects…

2. สร้าง Test Project ตั้งชื่อว่า Infrastructure.Orm.NHibernateMappings.Test ทำตามภาพข้างล่างครับ

3. หลังจากสร้าง project test เรียบร้อยแล้ว คุณจะพบว่ามี file UnitTest1.cs สร้างมาให้ 1 file ผมขอสรุปโครงสร้างของ project ใน Solution Explorer ตามภาพนี้

4. เพิ่ม library Enterprise.Domains และ Infrastructure.Orm.NHibernateMappings โดย click-ขวา ที่ References | Add References… ไปที่ tab Projects เลือกตามภาพแล้วกด OK

5. เพิ่ม library NHibernate ได้แก่ NHibernate.dll, NHibernate.ByteCode.Castle.dll โดย ทำเหมือนข้อ 4 แต่ให้เลือก browse ไปที่ folder ของ NHibernate ที่ dowload มาแล้ว หรือ dowload ได้ที่ http://nhforge.org/Default.aspx

6. ไปที่ drive ใดก็ได้บนเครื่องของคุณ แล้วสร้าง folder ตั้งชื่อว่า deploys หลังจากนั้น copy file System.Data.SQLite.dll, System.Data.SQLite.lib และ System.Data.SQLite.Linq.dll ของ SQLite ที่ได้ทำการติดตั้งแล้ว จาก C:\Program Files (x86)\SQLite.NET\bin ดูภาพประกอบครับ

7. ไปที่ folder deploys ที่เตรียมไว้สร้าง file hibernate.cfg.xml ซึ่งเป็น config ของ NHibernate แล้วเขียน xml ตามข้างล่างนี้ลงไป เสร็จแล้วกด save

สรุปแล้วใน folder deploys จะมี file ต่างๆตามภาพข้างล่างนี้

8. ขั้นตอนนี้จะทำการเพิ่ม folder  deploys นี้เข้ามาใน Test projects ทุกครั้งเมื่อมีการ run unittest โดย ใน  Solution Explorer window click ไปที่ Solution Items > double click ที่ Local.testsettings มันจะ popup Test Sesttings ขึ้นมาให้เลือกตามภาพนี้

เอาละตอนนี้ เราก็พร้อมแล้วที่จะเขียน code Unit Test

เขียน Code ใน Unit test ทดสอบว่ามัน work ก่อนนำไปใช้งานกันจริงๆ… Actions!

1. ไปที่ file UnitTest1.cs เขียน code include packet ตามนี้เข้าไป

using NHibernate;
using NHibernate.Cfg;
using NHibernate.Linq;
using NHibernate.Tool.hbm2ddl;

using Enterprise.Domains;

2. ประกาศ object Configuration และ ISessionFactory เป็น global เพื่อใช้ในทุกๆ unit test method ตามนี้

Configuration _nhConfig;
ISessionFactory _sessionFactory;

3. ประกาศ method Setup ใน unit test เพื่อ config, สร้างฐานข้อมูล และ เพิ่มข้อมูลที่จำเป็นทั้งหมด สำหรับการทดสอบของเรา โดยมันจะทำงานเพียงครั้งเดียว เมื่อ run method unit test

        [TestInitialize]
        public void Setup()
        {
            Console.WriteLine("Setup");
            _nhConfig = new Configuration().Configure();
            _sessionFactory = _nhConfig.BuildSessionFactory();
            Console.WriteLine("NHibernate configured!");
            var schemaExport = new SchemaExport(_nhConfig);
            schemaExport.Create(false, true);
            Console.WriteLine("Generating database completed!");

            using (var session = _sessionFactory.OpenSession())
            using (var tran = session.BeginTransaction())
            {

                var act1 = new ActorRole() { Actor = "Harrison Ford", Role = "Indiana Jones" };
                session.Save(act1);
                var act2 = new ActorRole() { Actor = "Jack Nicholson", Role = "Edward Cole" };
                session.Save(act2);
                var act3 = new ActorRole() { Actor = "Morgan Freeman", Role = "Carter Chambers" };
                session.Save(act3);

                session.Save(
                new Movie()
                {
                    Name = "Raiders of the Lost Ark",
                    Description = "Awesome",
                    UnitPrice = 9.59M,
                    Director = "Steven Spielberg",
                    Actors = new List<ActorRole>() { act1 }
                });

                session.Save(
                new Movie()
                {
                    Name = "The Bucket List",
                    Description = "Good",
                    UnitPrice = 15M,
                    Director = "Rob Reiner",
                    Actors = new List<ActorRole>()
                    {
                    act2,
                    act3
                    }
                });
                Console.WriteLine("Create movies completed!");

                session.Save(
                new Book()
                {
                    Name = "NHibernate 3.0 Cookbook",
                    Description = "NHibernate examples",
                    UnitPrice = 50M,
                    Author = "Jason Dentler",
                    ISBN = "978-1-849513-04-3"
                });

                Console.WriteLine("Create books completed!");
                tran.Commit();
            }
        }

4. ประกาศ unit test method สำหรับทดสอบตามต้องการ ในที่นี้ผม เขียนทดสอบให้แสดงข้อมูล products ที่ได้สร้างเตรียมไว้จากขั้นตอน setup ไว้แล้วเท่านั้น แบบนี้

        [TestMethod]
        public void TestGetAllProducts()
        {
            using (var session = _sessionFactory.OpenSession())
            {
                var query = from p in session.Query<Product>()
                            select p;

                query.ToList().ForEach(p =>
                {
                    Console.WriteLine("-----------------------------------");
                    Console.WriteLine("Nane: {0}, Description: {1} - Type: {2}", p.Name, p.Description, p);
                    if (p is Movie)
                    {
                        var movie = (Movie)p;
                        movie.Actors.ForEach(act =>
                        {
                            Console.WriteLine("\tActor: {0}, Role: {1}", act.Actor, act.Role);
                        });
                    }
                });
            }

        }

5. เอาละครับได้เวลา run แล้ว ให้ click-ขวา ที่ code method unit test TestGetAllProducts() ใน file UnitTest1.cs เลือก Run Tests ตามภาพ

6. ถ้าทุกอย่าง ok จะแสดง output ที่ Test Results เป็นสีเขียน เมื่อ double click ขึ้มมาดูในรายละเอียด จะแสดงแบบนี้

—————————————————————————————————————————————–

Setup
NHibernate configured!
Generating database completed!
Create movies completed!
Create books completed!
———————————–
Nane: Raiders of the Lost Ark, Description: Awesome – Type: Enterprise.Domains.Movie
Actor: Harrison Ford, Role: Indiana Jones
———————————–
Nane: The Bucket List, Description: Good – Type: Enterprise.Domains.Movie
Actor: Jack Nicholson, Role: Edward Cole
Actor: Morgan Freeman, Role: Carter Chambers
———————————–
Nane: NHibernate 3.0 Cookbook, Description: NHibernate examples – Type: Enterprise.Domains.Book

—————————————————————————————————————————————–

เสร็จแล้วครับกับ เริ่มต้น SQLite กับ NHibernate… Actions! ลองกลับไปดูที่ folder deploys คุณจะพบว่ามี file enterprise.s3db เพิ่มขึ้นมา มันคือ file database SQLite นั่นเอง มันได้ถูกสร้างโดยอัตโนมัติ ด้วย NHibernate.Tool.hbm2ddl จาก code คำสั่งนี้

            var schemaExport = new SchemaExport(_nhConfig);
            schemaExport.Create(false, true);

และถ้าคุณ install เครื่องมือ SQLite Administrator ไว้ที่เครื่องแล้วลอง double click file enterprise.s3db ซึ่งมันจะถูกเปิดด้วย SQLite Administrator ที่จะแสดงขึ้นมาแบบนี้

OK ครับผมของจบบทความไว้เพียงเท่านี้

SourceCode

ขอบคุณครับ 🙂

ทุกอย่างจะสำเร็จได้ด้วยการคิด และลงมือทำ เดี๋ยวนี้!

Chav:P

Advertisements

#net, #nhibernate