Asp.net MVC 2 + Castle + NHibernate 项目实战(1)

2010-09-28 21:00

Asp.net MVC 2 + Castle + NHibernate 项目实战(1)

by 李锡远

at 2010-09-28 13:00:00

original http://www.cnblogs.com/taven/archive/2010/09/28/1837478.html


作者: 李锡远 发表于 2010-09-28 13:00 原文链接 阅读: 829 评论: 6

本文将开始一步一步地使用Asp.net MVC 2 + Castle + NHibernate 开发一个项目。

 

首先,第一步是创建一个解决方案,项目结构如下:

 

需要引用的DLL库文件,我们全部放在RoRoWo.Common.DependLib下:

 

 根据表的结构,如图: 

 

 

现在我们开始为表结构创建实体类,以BlogCategory表为例,我们根据该表的字段名称和数据类型创建一个POCO类,放在RoRoWo.Domain.Entities下,代码内容如下:

 代码

namespace RoRoWo.Domain {
    
    
public class Blogcategory {
        
public Blogcategory() { }
        
public virtual int Cateid { getset; }
        
public virtual IList<Blogarticle> Blogarticles { getset; }
        
public virtual string Catename { getset; }
        
public virtual int Parentid { getset; }
        
public virtual int State { getset; }
        
public virtual int Sortid { getset; }
        
public virtual int Articlecount { getset; }
        
public virtual System.DateTime Createtime { getset; }
        
public virtual string Note { getset; }
    }
}

 

 在这里,我推荐一个可以生成NHibernate映射对象代码的工具(开源的),项目地址:NHibernate Mapping Generator(它同时支持 hbm.xml文件的方式、Fluent Mapping方式、Castle ActiveRecord方式)

接下来,要为这个类创建一个映射关系,我这里使用配置文件的方式,但是正式项目推荐使用Fluent方式。我们创建一个XML文件,文件名为“Blogcategory.hbm.xml”,放在RoRoWo.Domain.Mappings下,内容如下:

代码
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping assembly="RoRoWo.Domain" namespace="RoRoWo.Domain" xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
    
<class name="Blogcategory" table="BlogCategory">
        
<id name="Cateid" column="CateID">
            
<generator class="native" />
        
</id>
        
<property name="Catename" column="CateName" />
        
<property name="Parentid" column="ParentID" />
        
<property name="State" column="State" />
        
<property name="Sortid" column="SortID" />
        
<property name="Articlecount" column="ArticleCount" />
        
<property name="Createtime" column="CreateTime" />
        
<property name="Note" column="Note" />
    
</class>
</hibernate-mapping>

 

 

这里就是一个典型的映射关系了,如果有一对多,多对多的表关系,也是在这个配置中进行维护。

创建这个XML后,还有个很重要的操作,就是将其设为“嵌入的资源” ,鼠标右键查看“Blogcategory.hbm.xml”文件属性,将“生成操作”项的“内容”改为“嵌入的资源”,如图:

 

 到此,一个映射关系的实体就建立好了,下面我们就要来实现NHibernate对该表的增删改查操作了,我们把这些操作的实现放在RoRoWo.Data中。

注意,RoRoWo.Data需要添加对 “Castle.Core.dll” "Castle.DynamicProxy2.dll" "NHibernate.dll" "RoRoWo.Domain" 的引用。

 

在创建数据库操作类之前,我们需要创建一个 “SessionManager”类,它负责维护整个ORM中的上下文,这里我使用李永京的一个类,其代码如下:

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

using NHibernate;
using NHibernate.Cfg;

namespace RoRoWo.Data
{
    
public class SessionManager
    {
        
private ISessionFactory _sessionFactory;
        
public SessionManager()
        {
            _sessionFactory 
= GetSessionFactory();
        }
        
private ISessionFactory GetSessionFactory()
        {
            
return (new Configuration()).Configure().BuildSessionFactory();
        }
        
public ISession GetSession()
        {
            
return _sessionFactory.OpenSession();
        }
    }
}

 

 

我们创建一个“BlogCategoryRespository.cs”文件,其代码如下:

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

using NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;
using RoRoWo.Domain;

namespace RoRoWo.Data
{
    
public class BlogCategoryRespository
    {
        
private ISession _session;
        
public ISession Session
        {
            
set
            {
                _session 
= value;
            }
        }

        
public BlogCategoryRespository(ISession session)
        {
            _session 
= session;
        }

        
public Blogcategory GetById(int cateId)
        {

            
return _session.Get<Blogcategory>(cateId);
        }

        
public void Create(Blogcategory dto)
        {
            _session.Save(dto);
            _session.Flush();
        }

        
public int CreateAndReturn(Blogcategory dto)
        {
            
int newid = (int)_session.Save(dto);
            _session.Flush();
            
return newid;
        }

        
/// <summary>
        
/// 使用事务
        
/// </summary>
        
/// <param name="dto"></param>
        
/// <returns></returns>
        public int CreateTransaction(Blogcategory dto)
        {
            
using (ITransaction tx = _session.BeginTransaction())
            {
                
try
                {
                    
int newId = (int)_session.Save(dto);
                    _session.Flush();
                    tx.Commit();
                    
return newId;
                }
                
catch (HibernateException)
                {
                    tx.Rollback();
                    
throw;
                }
            }
        }

        
public void UpdateCustomer(Blogcategory dto)
        {
            _session.Update(dto);
            _session.Flush();
        }

        
public void SaveOrUpdate(IList<Blogcategory> dtos)
        {
            
foreach (var c in dtos)
            {
                _session.SaveOrUpdate(c);
            }
            _session.Flush();
        }

        
public void Delete(Blogcategory dto)
        {
            _session.Delete(dto);
            _session.Flush();
        }

        
public IList<Blogcategory> From()
        {
            
//返回所有Blogcategory类的实例
            return _session.CreateQuery("from Blogcategory")
                .List
<Blogcategory>();
        }

        
public IList<int> Select()
        {
            
//返回所有Blogcategory的CateId
            return _session.CreateQuery("select c.CateId from Blogcategory c")
                .List
<int>();
        }

        
public IList<Blogcategory> Where()
        {
            
return _session.CreateQuery("from Blogcategory c where c.CateId='3'")
                .List
<Blogcategory>();
        }

        
public IList<Blogcategory> GetGreaterThan(int CateId)
        {
            
//return _session.CreateQuery("select from Blogcategory c where c.CateId > :cid")
            
//    .SetInt32("cid", CateId)
            
//    .List<Blogcategory>();

            
return _session.CreateCriteria(typeof(Blogcategory))
            .Add(Restrictions.Gt(
"CateId", CateId))
            .List
<Blogcategory>();

        }

        
public IList<Blogcategory> CreateCriteria()
        {
            ICriteria crit 
= _session.CreateCriteria(typeof(Blogcategory));
            crit.SetMaxResults(
50);
            IList
<Blogcategory> blogcategorys = crit.List<Blogcategory>();
            
return blogcategorys;
        }

        
public IList<Blogcategory> Narrowing()
        {
            IList
<Blogcategory> blogcategorys = _session.CreateCriteria(typeof(Blogcategory))
                .Add(Restrictions.Like(
"Catename""s%"))
                .Add(Restrictions.Between(
"Parentid""1""3"))
                .List
<Blogcategory>();
            
return blogcategorys;
        }

        
public IList<Blogcategory> Query()
        {
            Blogcategory dtoSample 
= new Blogcategory() { Catename = "sss", Parentid = 0 };
            
return _session.CreateCriteria(typeof(Blogcategory))
                .Add(Example.Create(dtoSample))
                .List
<Blogcategory>();
        }

        
public IList<Blogcategory> UseQueryByExample_Get(Blogcategory dtoSample)
        {
            Example example 
= Example.Create(dtoSample)
                .IgnoreCase()
                .EnableLike()
                .SetEscapeCharacter(
'&');
            
return _session.CreateCriteria(typeof(Blogcategory))
               .Add(example)
               .List
<Blogcategory>();
        }

    }
}

 

 

该代码具有了对一个表的基本操作,现在我们就来创建一个单元测试,测试一下插入数据。

在创建插入操作时,我们要能使NHibernate正常工作,还需要创建一个配置文件,我们创建一个XML文件,文件名为“hibernate.cfg.xml”,放在RoRoWo.UnitTest下,其内容为:

代码
<?xml version="1.0" encoding="utf-8"?>
<hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2" >
    
<session-factory>
        
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
        
<property name="connection.connection_string">
            Data Source=.;Initial Catalog=RoRoWoDB;User ID=sa;Password=2010;
        
</property>
        
<property name="adonet.batch_size">10</property>
        
<property name="show_sql">true</property>
        
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
        
<property name="use_outer_join">true</property>
        
<property name="command_timeout">10</property>
        
<property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
        
<property name="proxyfactory.factory_class">
            NHibernate.ByteCode.Castle.ProxyFactoryFactory,
            NHibernate.ByteCode.Castle
        
</property>
        
<mapping assembly="RoRoWo.Domain"/>
    
</session-factory>
</hibernate-configuration>

 

 其中“Data Source=.;Initial Catalog=RoRoWoDB;User ID=sa;Password=2010;”是我的数据库连接,您可以改为您的。

 

现在我们添加一个单元测试(不明白如何添加的请参考相关资料),先测试插入方法,其代码如下:

 代码

        /// <summary>
        
///Create 的测试
        
///</summary>
        [TestMethod()]
        
public void CreateTest()
        {
            SessionManager sessionManager 
= new SessionManager();
            ISession session 
= sessionManager.GetSession();
            BlogCategoryRespository target 
= new BlogCategoryRespository(session);
            Blogcategory dto 
= new Blogcategory();

            dto.Catename 
= "新分类" + new Random().Next(100000999999).ToString();
            dto.Parentid 
= 0;
            dto.State 
= 0;
            dto.Createtime 
= DateTime.Now;

            
int newid = target.CreateAndReturn(dto);
            Assert.IsTrue(newid 
> 0);
        }

 

 执行单元测试,可以通过测试,并且在数据库中已经成功插入了一条记录,结果完全正确;

我们接着对查询方法进行测试,我们将测试代码如下:

代码
        /// <summary>
        
///GetById 的测试
        
///</summary>
        [TestMethod()]
        
public void GetByIdTest()
        {
            SessionManager sessionManager 
= new SessionManager();
            ISession session 
= sessionManager.GetSession();
            BlogCategoryRespository target 
= new BlogCategoryRespository(session);
            
int cateId = 3;
            Blogcategory actual;
            actual 
= target.GetById(cateId);
            Assert.AreEqual(cateId, actual.Cateid);

        }

        
/// <summary>
        
///From 的测试
        
///</summary>
        [TestMethod()]
        
public void FromTest()
        {
            SessionManager sessionManager 
= new SessionManager();
            ISession session 
= sessionManager.GetSession();
            BlogCategoryRespository target 
= new BlogCategoryRespository(session);
            IList
<Blogcategory> actual;
            actual 
= target.From();
            Assert.IsTrue(actual.Count 
> 0);

        }

        
/// <summary>
        
///Select 的测试
        
///</summary>
        [TestMethod()]
        
public void SelectTest()
        {
            SessionManager sessionManager 
= new SessionManager();
            ISession session 
= sessionManager.GetSession();
            BlogCategoryRespository target 
= new BlogCategoryRespository(session);
            IList
<int> actual;
            actual 
= target.Select();
            Assert.IsTrue(actual.Count 
> 0);
        }

        
/// <summary>
        
///Where 的测试
        
///</summary>
        [TestMethod()]
        
public void WhereTest()
        {
            SessionManager sessionManager 
= new SessionManager();
            ISession session 
= sessionManager.GetSession();
            BlogCategoryRespository target 
= new BlogCategoryRespository(session);

            IList
<Blogcategory> actual;
            actual 
= target.Where();
            Assert.IsTrue(actual.Count 
> 0);
        }

        
/// <summary>
        
///GetGreaterThan 的测试
        
///</summary>
        [TestMethod()]
        
public void GetGreaterThanTest()
        {
            SessionManager sessionManager 
= new SessionManager();
            ISession session 
= sessionManager.GetSession();
            BlogCategoryRespository target 
= new BlogCategoryRespository(session);
            
int CateId = 0// TODO: 初始化为适当的值
            IList<Blogcategory> actual;
            actual 
= target.GetGreaterThan(CateId);
            Assert.IsTrue(actual.Count 
> 0);

        }

 

 

 测试结果全部绿灯通过:

 

下一篇,我将谈谈如何配置一对多和多对多的表映射关系。

 

该例子的完整代码可以到开源平台下载,地址: http://rorowoproject.codeplex.com

文章中如有不足之处,望大家多指正。

 

 

 

评论: 6 查看评论 发表评论

程序员找工作,就在博客园


最新新闻:
· 张朝阳反思搜狐微博 亲自挂帅挑战新浪(2010-09-28 22:28)
· 调查显示1/4的美国人想要购买Android平板电脑(2010-09-28 22:22)
· Windows Live Spaces气数未尽,网易、搜狐争先抢“尸”(2010-09-28 21:40)
· ZFS文件系统建立者离开Oracle(2010-09-28 21:36)
· 雅虎为何难以实施分红?(2010-09-28 21:35)

编辑推荐:今天你抛弃了ASP.NET了吗?问题篇

网站导航:博客园首页  个人主页  新闻  闪存  小组  博问  社区  知识库