zoukankan      html  css  js  c++  java
  • Asp.net MVC 2 + Castle + NHibernate 项目实战(1)

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

     

    在开始之前,我先对这三个组件做一个简单的介绍:

     Asp.net MVC 

    它是微软提供的一个基于MVC标准的Web开发模式,其典型特点是有控制器和视图;在这之前,.NET下的Web开发模式大多是采用WebForm,其典型特点是服务端控件和后台触发事件; 

     NHibernate

    它是一个ORM框架,使用Java的SSH做过项目开发的人就非常熟悉了,当前最新版本为NHibernate 3.0,听说完全支持Linq查询语句了,以前只支持HQL语句。 

     Castle

    它是一个非常大的框架,包含IoC、MVC、ORM、AOP等,这次我只用到其IoC的功能。

     

    关于IoC

    IoC的英文是Inversion of Control,中文意思是控制反转,也有称其为Dependence Injection,中文意思是依赖注入,也就是DI;

    除了Castle可以作IoC 外,还有著名的Spring.Net、Unity等,在我另外一个开源博客项目 http://rorowo.codeplex.com/ 中就用到了微软的Unity 2.0作为IoC。

    好了,废话不多说,下面开始。 

     

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

     

    需要引用的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

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

  • 相关阅读:
    SpringSecurity 框架学习 3
    SpringSecurity 框架学习 项目创建
    nginx 限制ip访问
    nginx 负载均衡,后端服务获取不到域名问题
    Linux 安装 Nginx
    Linux 常用命令
    springcloud 服务追踪
    Hystrix 服务容错
    Scrum立会报告+燃尽图(十二月十日总第四十一次):用户推广
    Final发布:文案+美工展示博客
  • 原文地址:https://www.cnblogs.com/taven/p/1837478.html
Copyright © 2011-2022 走看看