ASP.NET MVC+NHibernate (CURD)
今天的这篇博文是关于在ASP.NET MVC 中使用Nhibernate并且对其session进行管理。当你阅读这篇博文时,默认你已经熟悉Nhibernate和ASP.NET MVC。其实在.net中有一款ORM框架:Entity Framework。我个人觉得在企业级项目中使用EF框架并不如使用NHibernate好,况且hibernate在jsp中已经是运用的十分的好了,Nhibernate只不过是将应用平台拓展到.net中。
首先呢,建立一个MVC的工程。这个在这就不截图了,总所周知使用NHIbernate要进行配置。我们在此将配置文件放在Models下的Nhibernate文件夹中如图:
配置的信息:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
<session-factory name="NHibernate.Test">
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">
Server=(local);initial catalog=Mvc_test;Integrated Security=SSPI
</property>
<property name="dialect">NHibernate.Dialect.MsSql2012Dialect</property>
<property name="show_sql">false</property>
<property name="hbm2ddl.auto">update</property>
<property name="adonet.batch_size">10</property>
<property name="command_timeout">60</property>
<property name="current_session_context_class">web</property><!--这个地方很重要,没有这句话,会报 No current session 当绑定的时候-->
<!--Mapping-->
<mapping resource="Ebuy.Website.Models.Nhibernate.Employee.hbm.xml" assembly="Ebuy.Website" file=""/>
</session-factory>
</hibernate-configuration>
正如我在配置文件中的注释一样,那句话十分的重要,没有那句话项目运行会报错,报错的原因也是(大概意思):没有上下文的session
在上面的配置文件中我将要映射的类文件也写在上面了,当然你也可以在SessionFactory中进行添加,我个人认为这样写比较方便管理,并且一目了然,纯属个人习惯吧。到目前为止我们将配置文件配好了,对了!一个十分重要并且很容易被遗忘的步骤:在配置文件配好了以后一定要将其xml属性的Copy to output Directory设置为:Copy always。不然一会报错。接着我们Employee类进行mapping.我们想把Employee类写出来吧:
public class Employee
{
public virtual int? Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Designation { get; set; }
}
其映射代码为:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Ebuy.Website" namespace="Ebuy.Website.Models">
<class name="Employee" table="Employee" dynamic-update="true">
<cache usage="read-write"/>
<id name="Id" column="Id" type="int">
<generator class="native"/>
</id>
<property name="FirstName" column="FirstName" length="20"/>
<property name="LastName" column="LastName" length="20" />
<property name="Designation" column="Designation" length="50"/>
</class>
</hibernate-mapping>
恩,好了到目前为止,我们将最为基础的步骤走完了,几下来的几个步骤是十分的重要,我也是在网上找了一个遍加上个人的想法综合得到的,如果有什么不对的地方欢迎指出。同时:show me your code!
如上面的截图一样,我们在Models下有一个SessionManagement.cs文件。这个类是对Session的管理。这个类继承了ActionFilterAttribute.所以我们可以重写onActionExecution和onActionExecuted.具体的请看贴出的代码;
using System;
using System.Web;
using System.Web.Mvc;
using NHibernate;
using NHibernate.Context;
namespace Ebuy.Website.Models
{
public class SessionManagement:ActionFilterAttribute
{
public SessionManagement()
{
SessionFactory = MvcApplication.SessionFactory;
}
private ISessionFactory SessionFactory { get; set; }
public ISession _session;
//当web程序执行一个action时
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
//打开session
_session = SessionFactory.OpenSession();
//绑定当前的session
CurrentSessionContext.Bind(_session);
//开始执行一个事务
_session.BeginTransaction();
}
//当一个web程序执行完action时的操作
public override void OnActionExecuted(ActionExecutedContext acionExcutedContext)
{
//获取当前的session
_session = SessionFactory.GetCurrentSession();
//获取当前session的事务
var transaction = _session.Transaction;
if (transaction != null && transaction.IsActive)
{
//提交事务
transaction.Commit();
}
//将当前的session从当前的SessionFactory解绑
_session = CurrentSessionContext.Unbind(SessionFactory);
//关闭session
_session.Close();
_session.Dispose();
}
}
}
或许大家在这里会问在构造函数里MvcApplicaction怎么会有SessionFactory这个属性。大家别急,我在这讲讲我实现对Session管理的思路。我们可以在程序启动时,就立即建立一个sessionFactory以便对session的管理,同时呢,我们可以运用memcached对Nhibernate进行二级缓存的管理,当然了这也是后话了。同时找到Nhibernate的config文件。这是我的Global.asax文件:
namespace Ebuy.Website
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public static ISessionFactory SessionFactory { get; private set; }
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
InitializeSessionFactory();
}
private void InitializeSessionFactory()
{
var configuration = new Configuration();
var configurationPath = HttpContext.Current.Server.MapPath(@"~/Models/Nhibernate/hibernate.cfg.xml");
SessionFactory = configuration.Configure(configurationPath).BuildSessionFactory();
}
}
}
好了,我们进行到这,就还有最后一个步骤了,就是实现CURD,我们在Controllers中创建一个cs文件如图:
具体的如下代码:
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Web;
5: using System.Web.Mvc;
6: using NHibernate;
7: using Ebuy.Website.Models;
8:
9: namespace Ebuy.Website.Controllers
10: {
11:
12: public class EmployeeController : Controller
13: {
14: //
15: // GET: /Employee/
16:
17: [SessionManagement]
18: public ActionResult Index()
19: {
20: //在这里为什么写的和下面的不同的原因:在SessionManagement中已经将一个Session绑定到当前的
21: //线程中,所以在这里可以通过GetCurrentSession()来获得当前已经打开的session
22: ISession _session = MvcApplication.SessionFactory.GetCurrentSession();
23: var employees = _session.CreateQuery("from Employee").List<Employee>();
24: return View(employees);
25: }
26:
27: // [SessionManagement]
28: public ActionResult Create()
29: {
30: return View();
31: }
32:
33:
34: [HttpPost,SessionManagement]
35: public ActionResult Create(Employee employee)
36: {
37: int isSave = new NHibernateRespository().Create(employee);
38: if (isSave > 0)
39: {
40: return RedirectToAction("Index");
41: }
42: return View();
43: }
44:
45: [SessionManagement]
46: public ActionResult Edit(int id)
47: {
48: var employee = new NHibernateRespository().Get(id);
49: return View(employee);
50: }
51:
52: [HttpPost,SessionManagement]
53: public ActionResult Edit(int id, Employee employee)
54: {
55: try
56: {
57: new NHibernateRespository().Edit(id, employee);
58: return RedirectToAction("Index");
59: }
60: catch (Exception ex)
61: {
62: return View();
63: }
64:
65: }
66:
67: [SessionManagement]
68: public ActionResult Details(int id)
69: {
70: var employee = new NHibernateRespository().Get(id);
71: return View(employee);
72:
73: }
74:
75: [SessionManagement]
76: public ActionResult Delete(int id)
77: {
78: var employee = new NHibernateRespository().Get(id);
79: return View(employee);
80: }
81:
82: [HttpPost,SessionManagement]
83: public ActionResult Delete(int id, Employee employee)
84: {
85: try
86: {
87: new NHibernateRespository().Delete(id, employee);
88: return RedirectToAction("Index");
89: }
90: catch (Exception ex)
91: {
92: return View();
93: }
94:
95: }
96:
97: }
98: }
重要的解释,我已经在代码中注释了。
在这里,是一个整体的controllers。那我们在创建Index时,要创建它的view这样:
就是勾选它的Create a strongly-typed view使用的Model class 就是我们的Employee类,这样写可以帮组我们省了一堆事,当然了,这里我们仅仅是一个CURD的列子,具体的还要看具体的业务需求。这里特别注意在选着Scaffold template时,要选着我们对应的CURD操作,这里的Index是一个List。其他的一一对应!
controllers中的EmployeeControllers对应的Views就是这样了:
最后的补充:
在上面的列子中,我们实现了最为简单的CURD,本文不是着重于CURD,本文的意义在于在ASP.NET MVC 中使用NHibernate并且对其Session进行管理,以便达到最好的使用效果,毕竟打开一个openSession()是要占用资源了。
在博文中如果有不对或者有所欠缺的地方,欢迎各位园友指出,本人也在不断的学习中。如有问题email me!
本文属于原创博文,允许转载,但是请保留原文的连接!