ASP.NET MVC กับ Fluent NHibernate คู่หูสุดเจ๋ง… Actions!

เตรียมตัวกันก่อน

บทความนี้ผมจะนำเสนอวิธีการติดต่อสื่อสารกับ database server ด้วย Fluent NHibernate ใน application web ที่พัฒนาด้วย  ASP.NET MVC สิ่งที่จำเป็นมากก่อนที่คุณจะทำตามบทความนี้ได้ คุณจะต้องอ่านบทความ

สร้าง mapping fluently Domain Model ด้วย Fluent NHibernate… Actions! นี้ซะก่อน แล้วทำการปฏิบัติตามขั้นตอน จนกระทั้งทดสอบผ่านแล้ว คุณจึงจะสามารถทำตามบทความนี้ได้สมบูรณ์ ส่วนเนื้อหาเบื้องต้นของ ASP.NET MVC อ่านได้จากบทความ ASP.NET MVC 3: แนะนำให้รู้จัก หลังจากที่คุณอ่านบทความเรื่อง Fluent NHibernate แล้วคุณก็จะมี domain model พร้อมกับ mapping fluently class ตามภาพข้างล่างนี้ไว้พร้อมแล้วนะครับ

ลำดับต่อไปคุณต้องแน่ใจว่ามี database server ติดตั้งอยู่ในเครื่องของคุณแล้ว ของผมใช้ PostgreSQL ครับ เมื่อเปิดมาแล้วคุณจะต้องมีฐานข้อมูล enterprise พร้อมกับ table Product เตรียมไว้เรียบร้อยแล้ว ตามภาพ

เอาละเมื่อคุณพร้อมแล้ว ผมจะเริ่มเลยละกัน

Actions!

เริ่มต้นสร้าง ASP.NET 3 Web Application

1. เปิด Visual Studio 2010 เลือก New Projects > Web > ASP.NET 3 Web Application ตั้งชื่อว่า MyEnterpriseApplication ตามภาพครับ

2. ที่หน้าจอที่ 2 ให้ click เลือก Empaty , View Engine เป็น Razor, check HTML5 หลังจากนั้นกด OK

ตอนนี้เราก็มี project wep แล้วขั้นต่อมาเราจะต้อง add library ทุกสิ่งอย่างที่จำเป็นเข้ามาที่ projects

Add All Library

1. ไปที่ menu > Tools > Library Packege Manager > Package Manager Console ตามภาพ (ขั้นต้อนนี้ผมลืมบอกคุณ โดยปกติเครื่องคุณจะไม่มี เครื่องมือนี้อยู่ ให้ไป downlaod แล้ว install มันก่อนได้จาก http://nuget.codeplex.com/)

2. มันจะ show console ที่มี shell PK> ขึ้นมา ให้พิมพ์ Install-Package FluentNHibernate ลงไป กด enter รอจนกระทั้งมัน load เสร็จครับ

Successfully installed ‘Iesi.Collections 3.1.0.4000’.
Successfully installed ‘NHibernate 3.1.0.4000’.
Successfully installed ‘Castle.Core 2.5.2’.
Successfully installed ‘NHibernate.Castle 3.1.0.4000’.
Successfully installed ‘FluentNHibernate 1.2.0.712’.
Successfully added ‘Iesi.Collections 3.1.0.4000’ to MyEnterpriseApplication.
Successfully added ‘NHibernate 3.1.0.4000’ to MyEnterpriseApplication.
Successfully added ‘Castle.Core 2.5.2’ to MyEnterpriseApplication.
Successfully added ‘NHibernate.Castle 3.1.0.4000’ to MyEnterpriseApplication.
Successfully added ‘FluentNHibernate 1.2.0.712’ to MyEnterpriseApplication.

3. add reference .Net Data Provider for PostgreSQL เข้าไปครับโดยมันจะอยู่ที่ folder ประมาณนี้ครับ C:\Program Files (x86)\PostgreSQL\Npgsql\ms.net4.0\ ถ้าไม่มีให้ไปอ่านบทความ Fluent NHibernate ก่อนครับ

4. สุดท้ายเราก็เพิ่ม library Enterprise.Domains และ Infrastructure.Orm.FluentNHibernate ที่ทำไว้แล้วเข้ามาใน project สรุป project web ของคุณจะต้องมี references ตามภาพนี้

การ add references ทั้งหมดเรียบร้อยครับ ขั้นต่อไปก็ เริ่ม code กันเลย

เติม Code สร้าง App

ผมจะทำ application แสดงรายการหนังสือ ที่สามารถแก้ไข เพิ่มรายการหนังสือใหม่ และลบออกได้

1.ก่อนอื่นผมต้องการจัดการ session factory เพื่อให้ web application หน้าใดๆก็แล้วแต่ใช้ session factory เดียวกันทุกครั้งที่เกิด action เปิดไปที่  file Global.asax.cs แล้ว using library ต่างๆตามนี้เข้าไป

using FluentNHibernate.Cfg;
using NHibernate.ByteCode.Castle;
using FluentNHibernate.Cfg.Db;
using Infrastructure.Orm.FluentNHibernate;

2. เพิ่ม propery SessionFactory  ของ class MvcApplication และให้กำหนดได้จากตัวเองเท่านั้น(private)

public static ISessionFactory SessionFactory{ get; private set; }

3. ไปที่ method Application_Start ของ class MvcApplication เพิ่ม code fluently NHibernate configuration ไปยังฐานข้อมูล และ config mapping class ตามนี้

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);

//fluently Nhibernate configuration ไปยังฐานข้อมูล และ config mapping class
var nhConfig = Fluently.Configure()
.ProxyFactoryFactory<ProxyFactoryFactory>()
.Database(PostgreSQLConfiguration.Standard
.ConnectionString(connstr => connstr
.Host(“localhost”)
.Port(5432)
.Database(“enterprise”)
.Username(“kading”)
.Password(“1234”)))
.Mappings(mappings => mappings.FluentMappings.AddFromAssemblyOf<ProductMapping>())
.BuildConfiguration()
.SetProperty(“current_session_context_class”, “thread_static”);

SessionFactory = nhConfig.BuildSessionFactory();

}

4. ตอนนี้ผมได้ SessionFactory จากที่เดียวแล้ว ต่อมาเมื่อผมต้องการใช้ session ใน controller ที่ใดๆ ผมก็เพียงแต่เรียกได้จาก MvcApplication ของผมได้เลย แล้วตอนนี้ผมต้องการ persit domain model ไปยัง database ของผมใน action controller ใดๆโดยทุกครั้งที่เริ่ม action session จะถูกเปิด และหลังจากเสร็จ action แล้ว session จะต้องถูกปิดดดยอัตโนมัติ ผมจึงต้องเขียน ActionFilterAttribute แล้วระบุไว้ใน action ทุกครั้งที่ต้องการ persitance domain model ไปยัง database ดังนั้นเพิ่ม class  NHibernateSessionAttribute  ที่มี base เป็น ActionFilterAttribute ได้ดังนี้

//NHibernateSessionAttribute.cs

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class NHibernateSessionAttribute : ActionFilterAttribute
{
public NHibernateSessionAttribute()
{

}
protected ISessionFactory sessionFactory
{
get
{
return MvcApplication.SessionFactory;
}
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var session = sessionFactory.OpenSession();
            CurrentSessionContext.Bind(session);
        }
public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            var session = CurrentSessionContext.Unbind(sessionFactory);
            session.Close();
        }
}

5. เพิ่มอีก attribute เพื่อสนับสนุนการ action ที่ต้องการควบคุม transaction เช่นการ edit, create และ delete

//NHibernateSessionAttribute.cs

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class NHibernateSessionAttribute : ActionFilterAttribute
{
public NHibernateSessionAttribute()
{

}
protected ISessionFactory sessionFactory
{
get
{
return MvcApplication.SessionFactory;
}
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var session = sessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var session = CurrentSessionContext.Unbind(sessionFactory);
session.Close();
}
}

6. เพิ่ม class BookController ไว้ที่ folder Controllers แบบ Empty controller ตามภาพ

7. เพิ่ม code action ใน BookController เพื่อทำงานต่างๆตามนี้ครับ

public class BookController : Controller
{
//
// GET: /Book/
[NHibernateSession]
public ActionResult Index()
{
//หน้าแรกให้แสดงรายการหนังสือทั้งหมด
var session = MvcApplication.SessionFactory.GetCurrentSession();
var books = session.QueryOver<Book>().List();
return View(books);
}

public ActionResult Create()
{
return View();
}

[HttpPost]
[NeedsPersistenceAttribute]
public ActionResult Create(Book newBook)
{
var session = MvcApplication.SessionFactory.GetCurrentSession();
session.Save(newBook);
return RedirectToAction(“Index”);
}

[NeedsPersistenceAttribute]
public ActionResult Edit(int id)
{
var session = MvcApplication.SessionFactory.GetCurrentSession();
var book = session.QueryOver<Book>().Where(b => b.Id == id).SingleOrDefault();
UpdateModel(book);
return View(book);
}

[NeedsPersistenceAttribute]
public ActionResult Delete(int id)
{
var session = MvcApplication.SessionFactory.GetCurrentSession();
var book = session.QueryOver<Book>().Where(b => b.Id == id).SingleOrDefault();
session.Delete(book);
return RedirectToAction(“Index”);
}
}

8. สร้าง view โดย click ขวาที่ action Index แล้วเลือก options ต่างๆตามภาพข้างล่างนี้ครับ

9. ลอง run ดูผลครับแต่ก่อน run ให้เปลี่ยน MapRoute Default ที่ Global.asax.cs กันก่อน ให้เปลี่ยนจาก Home เป็น Book เท่านี้ แล้ว run web ขึ้นมาได้เลย

10. คราวนี้ลอง click ที่ Create New ครับ

11. จบกัน error ซะแล้ว อ่าน error ตัวแดงๆดูก็จะรู้ว่ามัน Create view ไม่เจอนั่นเอง ครับกลับไปที่ BookController แล้ว เลือก action Create click ขวา สร้าง view เลือก options ตามภาพครับ

12. OK ละลองใหม่ครับเปิดขึ้นมาหน้าแรก แล้ว click ที่ New Create

ลองกรอกข้อมูลลงไป แล้วกดปุ่ม Create ดูเลยจะแสดงหน้านี้

13. ต่อไปก็สร้างหน้า Edit เหมือนเดิมกลับไปที่ BookController click ขวาที่ action method Edit แล้วเลือก Opetions ตามภาพ

OK เสร็จแล้วครับ ผมฝากให้ทดสอบ function Edit  และลองกด Delete ดูนะครับ

สุดท้ายผมคิดว่าที่แนะนำ ASP.NET MVC และ Fluent NHibernate เพราะมันเป็นคู่หูที่ ยอดเยี่ยมเลยทีเดียวสำหรับพัฒนา Web Application ที่มี Logic ที่มีความซับซ้อนมากๆอย่าง Business, ERP, Game หรือ Social Web Application แต่อาจจะไม่เหมาะสม และต้องใช้ความรู้มากไปกับ web ที่ต้องการแสดง Contents เฉยๆเท่านั้น

ขอบคุณครับ 🙂

Advertisements

#asp-net, #nhibernate