zoukankan      html  css  js  c++  java
  • ASP.NET Mvc + NHibernate + Unity Application Block 示例程序

    今天无意间看到了Unity Application Block (以下简称Unity),感觉很不错,用起来挺方便的说。于是一时兴起写了这个留言本的小示例。数据库操作采用的NHibernate,UI直接用的

    ASP.NET Mvc了。项目基于VS2010 + SQLServer 2005 ,就一个表的增删改查操作很简单。目的是为了体验下Unity的Ioc功能。

    国际惯例,先上个项目结构图

    项目只是演示使用,未建立公共类和配置项抽象出来等工作,各个项目如下:

    Guestbook.Biz 业务层,具体业务实现。这里只实现了增删改查

    Guestbook.Dal 持久层,基于NHibernate的ORM映射。实现增删改查

    Guestbook.IBiz 业务层接口,给UI引用实现解藕。UI层不直接引用具体业务类,实现面向接口

    Guestbook.IDal 持久层接口,给Biz引用实现解藕。方便更换不同数据库持久类(PS;虽然NHibernate 已经可以支持多库,这里纯为了娱乐)

    Guestbook.Model 持久实体,NHibernate的映射文件也放到这个类库里面了

    Guestbook.Unity 简单封装了一下Unity,传入相应接口即可New相应的在Web.Config中配置的具体业务类

    Guestbook.Web UI层,ASP.NET Mvc项目。控制器直接引用的业务接口IBiz和Model还有Unity其它全部不引用

    采取从下往上依次说各层的东西。首先从数据库。。。。(略)---从持久层说起吧。持久层采用了NHibernate基本配置和映射配置就不说了(hkgoogle),首先在Guestbook.Dal中写了一个NHibernateHelper帮助类,代码如下:

    代码
        /// <summary>
        
    /// NHibernate操作辅助类
        
    /// </summary>
        public class NHibernateHelper
        {
            
    private ISessionFactory _sessionFactory;
            
    public NHibernateHelper()
            {
                _sessionFactory 
    = GetSessionFactory();
            }
            
    private ISessionFactory GetSessionFactory()
            {
                Configuration cfg 
    = new Configuration();
                ISessionFactory sf 
    =
                    cfg.Configure().BuildSessionFactory();
                
    return sf;
            }
            
    public ISession GetSession()
            {
                ISession session 
    = _sessionFactory.OpenSession();
                
    return session;
            }
        }

    以上就是创建个NHibernate的Session。

    接下来是在Guestbook.IDal定义持久层相关的接口,首先是一个通用的增删改查接口,如下:

    代码
        /// <summary>
        
    /// 数据执行类接口
        
    /// </summary>
        
    /// <typeparam name="T"></typeparam>
        public interface IDbObject<T>
        {
            
    void Save(T entity);
            
    void Delete(T entity);
            
    void Update(T entity);
            T Load(
    int sysNo);
            IList
    <T> GetList();
        }

    定义基本的增删改查,是个泛型接口,这样实现它的类可以接收所有实本类,实现通用的方法。

    接下来在Guestbook.Dal 定义一个 DbObject<T>基类,实现IDbObject<T>的增删改查方法,并做具体的实现,像下面这样:

    代码
    /// <summary>
        
    /// 数据执行基础泛型类
        
    /// </summary>
        
    /// <typeparam name="T"></typeparam>
        public class DbObject<T>:IDbObject<T> where T:class
        {
            
    private ISession _session;
            
    public DbObject()
            {
                NHibernateHelper nhbHelper 
    = new NHibernateHelper();
                _session 
    = nhbHelper.GetSession();
            }
            
    #region IDbObject<T> 成员

            
    public void Save(T entity)
            {
                _session.Save(entity);
                _session.Flush();
            }

            
    public void Delete(T entity)
            {
                _session.Delete(entity);
                _session.Flush();
            }

            
    public void Update(T entity)
            {
                _session.Update(entity);
                _session.Flush();
            }

            
    public T Load(int sysNo)
            {
                
    return _session.Load<T>(sysNo);
            }

            
    public IList<T> GetList()
            {
                
    return _session.CreateCriteria<T>().AddOrder(NHibernate.Criterion.Order.Asc("SysNo")).List<T>();
            }

            
    #endregion

    比如 Save(T entity) 方法,实现具体的_session.Save(entity);_session.Flush();方法。通过NHibernate操作数据库。接下来就可以具体的持久业务类继承这个操作基类了。下面以Guestbook 为原型做相关讲解。为了数据层解藕,先建接口IGuestbookDal如下:

    代码
    /// <summary>
        
    /// 留言本数据操作接口
        
    /// </summary>
        public interface IGuestbookDal
        {
            
    void Save(GuestbookInfo entity);
            
    void Delete(GuestbookInfo entity);
            
    void Update(GuestbookInfo entity);
            GuestbookInfo Load(
    int sysNo);
            IList
    <GuestbookInfo> GetList();
        }

    然后在Guestbook.Dal中建一个具体持久类,这个类继承DbObject<GuestbookInfo>基类并实现IGuestbookDal接口,代码如下:

        /// <summary>
        
    /// 留言本数据处理类
        
    /// </summary>
        public class GuestbookDal:DbObject<GuestbookInfo>,IGuestbookDal
        {

        }

     具体操作已经在泛型基类DbObject中实现了,所以这个类不用再实现什么操作即可。再加比如UserDal;ProductDal都可以直接继承不用实现就可以了。大大减少了很多工作量(之前园子里有觉得应该取消泛型,这么好的东西给我留着吧。阿们)。这样持久层基本就完成了。接下来说说业务类。

    首先,一切为了解藕,一切为了面向接口。主阿,饶恕我吧。先在Guestbook.IBiz中定义个业务接口IGuestbookBiz吧:

    代码
      /// <summary>
        
    /// 留言本业务接口
        
    /// </summary>
        public interface IGuestbookBiz
        {
            
    void Save(GuestbookInfo entity);
            
    void Delete(GuestbookInfo entity);
            
    void Update(GuestbookInfo entity);
            GuestbookInfo Load(
    int sysNo);
            IList
    <GuestbookInfo> GetList();
        }

    这没啥说的了,再说大家都烦了。再紧跟着在Guestbook.Biz中建一个业务类GuestbookBiz 实现 以上接口:

    代码
    /// <summary>
        
    /// 留言本业务类
        
    /// </summary>
        public class GuestbookBiz:IGuestbookBiz
        {
            
    private IGuestbookDal _guestbookDal = UnityHelper.UnityToT<IGuestbookDal>("DalType");

            
    #region IGuestbookBiz 成员
            
    public void Save(GuestbookInfo entity)
            {
                _guestbookDal.Save(entity);
            }

            
    public void Delete(GuestbookInfo entity)
            {
                _guestbookDal.Delete(entity);
            }

            
    public void Update(GuestbookInfo entity)
            {
                _guestbookDal.Update(entity);
            }

            
    public GuestbookInfo Load(int sysNo)
            {
                
    return _guestbookDal.Load(sysNo);
            }

            
    public IList<GuestbookInfo> GetList()
            {
                
    return _guestbookDal.GetList();
            }

            
    #endregion
        }

    注意这句 private IGuestbookDal _guestbookDal = UnityHelper.UnityToT<IGuestbookDal>("DalType");,这里是业务层引用持久层,并不是直接New的,而是通过持久接口IGuestbookDal定义的,通过Unity加载进来的。这样就实现了相当成份的解藕了,不是由使用者去引用并实例被引用者,这个操作是由Ioc容器来做(这里是Unity)。这里用到了UnityHelper类了,它的写法如下(没有深入学习,只是基本操作):

    代码
    public static class UnityHelper
        {
            
    /// <summary>
            
    /// 通过Unity实组装对象泛型方法
            
    /// </summary>
            
    /// <typeparam name="T"></typeparam>
            
    /// <param name="entity"></param>
            
    /// <returns></returns>
            public static T UnityToT<T>(string name)
            {
                IUnityContainer container 
    = CreateContainer();
                T model 
    = container.Resolve<T>(name);
                
    return model;
            }
            
    /// <summary>
            
    /// 通过Unity实组装对象泛型方法
            
    /// </summary>
            
    /// <typeparam name="T"></typeparam>
            
    /// <param name="entity"></param>
            
    /// <returns></returns>
            public static T UnityToT<T>()
            {
                IUnityContainer container 
    = CreateContainer();
                T model 
    = container.Resolve<T>();
                
    return model;
            }
            
    /// <summary>
            
    /// 通过配置创建UnityContainer
            
    /// </summary>
            
    /// <returns></returns>
            public static IUnityContainer CreateContainer()
            {
                IUnityContainer container 
    = new UnityContainer();
                UnityConfigurationSection section 
    = (UnityConfigurationSection)
                    System.Configuration.ConfigurationManager.GetSection(
    "unity");
                section.Containers[
    "Guestbook"].Configure(container);
                
    return container;
            }
        }

    CreateContainer就是创建UnityContainer,它是Unity的核心所在。通过它就可以进行动态组装了。这里可以用代码创建也可以通过配置文件。我选择配置文件。因为直接写代码里面侵入太强了,失去了很多灵活装配的意义。配置我直接写在了Web.config里面,也可以单独写配置文件。我们在后面讲一下配置文件。UnityToT(string name)是我写的一个泛型方法,通过name查找相应的配置项去组装并反回接口的对象,T是我们的接口。使用就如上面:private IGuestbookDal _guestbookDal = UnityHelper.UnityToT<IGuestbookDal>("DalType");,<IGuestbookDal>就是接口,我们在配置里面有指定。"DalType"就是配置的名称。下面我们看一下相关的配置项:

    代码
    <unity>
        
    <containers>
          
    <container name="Guestbook">
            
    <types>
              
    <type name="BizType" type="Guestbook.IBiz.IGuestbookBiz,Guestbook.IBiz" mapTo="Guestbook.Biz.GuestbookBiz,Guestbook.Biz"/>
              
    <type name="DalType" type="Guestbook.IDal.IGuestbookDal,Guestbook.IDal" mapTo="Guestbook.Dal.GuestbookDal,Guestbook.dal"/>
            
    </types>
          
    </container>
        
    </containers>
      
    </unity>

    type节就是我们的对应配置项,name是我们前面泛型方法要传入的name,type为接口,mapTo为具体的业务类。比如上面的IGuestbookDal持久层接口对应的相应的GuestbookDal持久类,这样配置后Unity就会帮我们根据接口装配(实例化)实现类,并反回相应的实例对象,我们就可以通过这个对象实现具体业务了,比如:_dao.Save(entity);。

    这样我们的业务层也完成了,接下来就是UI层调用业务层就可以了。UI层我们一样通过Unity进行装配,UI层只引用实体类Guestbook.Model和Guestbook.IBiz业务层接口(当然用Unity要引用相应的UnityHelper类了)。这样UI层对业务层向下层次全部是弱依赖。UI我们基于的ASP.NET Mvc,所以我们在Controllers的里面进行业务层的装配并使用。我们以GuestbookInfo的列表显示为例,说一下。相应的Action叫说GuestbookList,代码如下:

    代码
     private static IGuestbookBiz _biz = UnityHelper.UnityToT<IGuestbookBiz>("BizType");
            public ActionResult GuestbookList()
            {
                IList
    <GuestbookInfo> guestbookList = _biz.GetList();
                return View(guestbookList);
            }

     private static IGuestbookBiz _biz = UnityHelper.UnityToT<IGuestbookBiz>("BizType");就是业务层装配了,我们通过业务接口IGuestbookBiz进行引用。通过_biz.GetList()就取得了相应的IList<GuestbookInfo>了。最后在相对应的View里面,指定Page Model ,像这样:Inherits="System.Web.Mvc.ViewPage<IList<Guestbook.Model.GuestbookInfo>>";然后在View中循环显示一下集合数据就可以了,大概像下面这样:

    代码
     <%foreach(var item in Model){ %>
          
    <table width="500" border="0" cellpadding="0" cellspacing="0">
          
    <tr>
          
    <th>姓名</th>
          
    <th style="background-color:White"><%=item.GuestName %></th>
          
    <th>性别</th>
          
    <th style="background-color:White"><%=item.Sex==1?"":"" %></th>
          
    </tr>
          
    <tr>
          
    <td colspan="4" height="50" valign="top">
          
    <%=item.GuestMessage %>
          
    </td>
          
    </tr>
          
    <tr>
          
    <td colspan="4"><%=Html.ActionLink("删除","Delete",new{sysno=item.SysNo}) %></td>
          
    </tr>
          
    </table>
        
    <%%>

    最后放一张运行的图片,其它的Save,Delete方式其本相同,这里就不多讲了。大家可以在这里下载源码(已上传)。

     

  • 相关阅读:
    response输出随机图片、定时刷新网页
    @Transactional注解使用心得
    mybatis缓存(一,二级别)
    数据库四大特性及数据库隔离级别
    mybatis @SelectKey加于不加的区别
    MYSQL索引类型+索引方法
    页面缓存例子
    概率生成模型超越神经网络
    生成学习
    过程量与状态量
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1866704.html
Copyright © 2011-2022 走看看