Asp.Net大型项目实践(4)-用NHibernate保存和查询我们的业务领域对象之实现基本的数据库访问(附源码)...

接上篇,完成NHibernate的Session管理和初始化之后,现在可以完成我们的数据库访问基类RepositoryNhbImpl了

  1. RepositoryNhbImpl数据库访问基类代码:
    ContractedBlock.gif ExpandedBlockStart.gif 代码
     
         
    namespace Demo.HIS.FrameWork.Repository.Nhb
    {
    public class RepositoryNhbImpl < T > : IRepository < T > where T : Entity
    {
    protected virtual ISession Session
    {
    get { return SessionBuilder.CreateSession(); }
    }
    #region IRepository<T> 成员
    public virtual T Load( string id)
    {
    try
    {
    T reslut
    = Session.Load < T > (id);
    if (reslut == null )
    throw new RepositoryException( " 返回实体为空 " );
    else
    return reslut;
    }
    catch (Exception ex)
    {
    throw new RepositoryException( " 获取实体失败 " , ex);
    }
    }

    public virtual T Get( string id)
    {
    try
    {
    T reslut
    = Session.Get < T > (id);
    if (reslut == null )
    throw new RepositoryException( " 返回实体为空 " );
    else
    return reslut;
    }
    catch (Exception ex)
    {
    throw new RepositoryException( " 获取实体失败 " , ex);
    }
    }

    public virtual IList < T > GetAll()
    {
    return Session.CreateCriteria < T > ()
    .AddOrder(Order.Asc(
    " CreateTime " ))
    .List
    < T > ();
    }

    public virtual void SaveOrUpdate(T entity)
    {
    try
    {
    Session.SaveOrUpdate(entity);
    Session.Flush();
    }
    catch (Exception ex)
    {
    throw new RepositoryException( " 插入实体失败 " , ex);
    }
    }

    public virtual void Update(T entity)
    {
    try
    {
    Session.Update(entity);
    Session.Flush();
    }
    catch (Exception ex)
    {
    throw new RepositoryException( " 更新实体失败 " , ex);
    }
    }

    public virtual void PhysicsDelete( string id)
    {
    try
    {
    var entity
    = Get(id);
    Session.Delete(entity);
    Session.Flush();
    }
    catch (System.Exception ex)
    {
    throw new RepositoryException( " 物理删除实体失败 " , ex);
    }
    }

    public virtual void Delete( string id)
    {
    try
    {
    var entity
    = Get(id);
    entity.IsDelete
    = true ;
    Update(entity);
    }
    catch (System.Exception ex)
    {
    throw new RepositoryException( " 删除实体失败 " , ex);
    }
    }
    #endregion
    }
    }
    注意: return SessionBuilder.CreateSession(); 这里通过我们上篇写的SessionBuilder去创建Session,具体实现其实就是简单的把NHibernate的方法封装了一下。
  2. 一般在信息管理系统中我们都会做“字典管理”功能,以方便客户自己维护一些下拉选项,如下图所示:
    2009122520292285.jpg
  3. 根据上面的需求,我们需要创建两个业务对象:
    字典类别DicCategory,虽然上图中被我搞花了,但你依然可以看出他是一个树形结构:) 而且可以预见在我们的系统中将来肯定有不少类似的树形结构,所以我们建立一个表示树形结构的基类:
    ContractedBlock.gif ExpandedBlockStart.gif 代码
     
         
    namespace Demo.HIS.FrameWork.DomainBase
    {
    /// <summary>
    /// 树型结构节点实体
    /// </summary>
    public abstract class TreeNode:Entity
    {
    /// <summary>
    /// 名称
    /// </summary>
    public virtual string Name { get ; set ; }

    /// <summary>
    /// 标识树形结构的编码
    /// </summary>
    public virtual string TreeCode { get ; set ; }

    /// <summary>
    /// 是否叶节点
    /// </summary>
    public virtual bool Leaf { get ; set ; }

    /// <summary>
    /// 父节点Id
    /// </summary>
    public virtual string ParentId { get ; set ; }


    /// <summary>
    /// 节点深度
    /// </summary>
    public virtual int Level { get ; set ; }

    }
    }

    注:在这个类里我们可以内聚一些树形结构的逻辑(与数据库访问无关),比如生产树节点编码的算法之类的,这里我就不写了
    字典类别DicCategory继承TreeNode:

    ContractedBlock.gif ExpandedBlockStart.gif 代码
     
         
    /// <summary>
    /// 字典类别
    /// </summary>
    public class DicCategory : TreeNode
    {
    public override string TreeCode
    {
    get
    {
    return base .TreeCode;
    }
    set
    {
    if (String.IsNullOrEmpty(value))
    throw new NotNullException();
    base .TreeCode = value;
    }
    }
    public override string Name
    {
    get
    {
    return base .Name;
    }
    set
    {
    if (String.IsNullOrEmpty(value))
    throw new NotNullException();
    base .Name = value;
    }
    }
    /// <summary>
    /// 包含的字典
    /// </summary>
    public virtual ISet < Dictionary > Dics { get ; set ; }


    /// <summary>
    /// 描述
    /// </summary>
    public virtual string Description { get ; set ; }

    /// <summary>
    /// 节点深度
    /// </summary>
    public override int Level
    {
    get
    {
    return base .Level;
    }
    set
    {
    if ( base .Level > 2 )
    throw new ValidationException( " 约定此业务对象的节点深度不超过2 " );
    base .Level = value;
    }
    }
    }

    可以看到我重写了基类的一些属性,使名称和编码不能为空,节点深度不能超过2级
    注意一下 这个属性 public virtual ISet<Dictionary> Dics { get; set; } 表示一个字典类别里包含了多个字典项(字典的类我们接着就建...),ISet<T>表示不重复的集合,实在整不明白你也可以理解成IList<T>。
    字典项Dictionary:

    ContractedBlock.gif ExpandedBlockStart.gif 代码
     
         
    /// <summary>
    /// 字典
    /// </summary>
    public class Dictionary : InputItem
    {
    /// <summary>
    /// 排序
    /// </summary>
    public virtual int Index { get ; set ; }

    /// <summary>
    /// 字典类别
    /// </summary>
    public virtual DicCategory Category { get ; set ; }

    /// <summary>
    /// 描述
    /// </summary>
    public virtual string Description { get ; set ; }
    }

    父类InputItem我们已经在Asp.Net大型项目实践(3)-业务领域对象建模的例子中讲过了,注意理解属性public virtual DicCategory Category { get; set; }

  4. 建立数据库表:
    2009122521272779.jpg
    可以看到表间关系是典型的一对多
    注:这里先给个数据建模工具PowerDesigner 12 的截图,后面会给出PD12的文件(PD支持导出数据库表,这里我是按Oracel10g建的物理模型)

  5. 建立NHibernate的Xml映射文件来映射对象与数据库表之间的关系
    注1:下载的NHibernate里含有两个.xsd文件,把他们放在X:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas目录里可实现智能提醒
    注2:你也可以CodeSmith这类的代码生成工具去生成你的Xml映射文件
    注3:如果你不喜欢用Xml映射,NHibernate也支持Attribute;
    注4:注意Xml映射文件的生成操作为嵌入资源
    2009122521435851.jpg
    字典类别DicCategory的Xml:

    ContractedBlock.gif ExpandedBlockStart.gif 代码
     
         
    <? xml version="1.0" encoding="utf-8" ?>
    < hibernate-mapping xmlns ="urn:nhibernate-mapping-2.2"
    assembly
    ="Infrastructure.Core" namespace ="Demo.HIS.Infrastructure.Core" >
    < class name ="Demo.HIS.Infrastructure.Core.DicCategory" table ="INFRA_DICCATEGORY" dynamic-insert ="true" dynamic-update ="true" where ="IsDelete=0" >
    < id name ="Id" column ="DICCATEGORY_ID" type ="String" >
    < generator class ="assigned" />
    </ id >
    < version name ="Version" column ="VERSION" unsaved-value ="0" />
    < property name ="Name" column ="NAME" type ="String" />
    < property name ="ParentId" column ="PARENT_ID" type ="String" />
    < property name ="TreeCode" column ="TREE_CODE" type ="String" />
    < property name ="Leaf" column ="LEAF" type ="Boolean" />
    < property name ="Description" column ="DESCRIPTION" type ="String" />
    < property name ="CreateTime" column ="CREATETIME" type ="DateTime" />
    < property name ="IsDelete" column ="ISDELETE" type ="Boolean" />
    < property name ="Level" column ="NODE_LEVEL" type ="Int32" />
    < set name ="Dics" table ="INFRA_DICTIONARY" generic ="true" lazy ="true" fetch ="subselect" where ="IsDelete=0" >
    < key column ="DICCATEGORY_ID" />
    < one-to-many class ="Demo.HIS.Infrastructure.Core.Dictionary" />
    </ set >
    </ class >
    </ hibernate-mapping >

    字典项Dictionary的Xml:

    ContractedBlock.gif ExpandedBlockStart.gif 代码
     
         
    <? xml version="1.0" encoding="utf-8" ?>
    < hibernate-mapping xmlns ="urn:nhibernate-mapping-2.2"
    assembly
    ="Infrastructure.Core" namespace ="Demo.HIS.Infrastructure.Core" >
    < class name ="Demo.HIS.Infrastructure.Core.Dictionary" table ="INFRA_DICTIONARY" dynamic-insert ="true" dynamic-update ="true" where ="IsDelete=0" >
    < id name ="Id" column ="DICTIONARY_ID" type ="String" >
    < generator class ="assigned" />
    </ id >
    < version name ="Version" column ="VERSION" unsaved-value ="0" />
    < property name ="Name" column ="NAME" type ="String" />
    < property name ="Code" column ="CODE" type ="String" />
    < property name ="InputCode1" column ="INPUT_CODE1" type ="String" />
    < property name ="InputCode2" column ="INPUT_CODE2" type ="String" />
    < property name ="InputCode3" column ="INPUT_CODE3" type ="String" />
    < property name ="Index" column ="INDEX_FIELD" type ="Int32" />
    < property name ="Description" column ="DESCRIPTION" type ="String" />
    < property name ="CreateTime" column ="CREATETIME" type ="DateTime" />
    < property name ="IsDelete" column ="ISDELETE" type ="Boolean" />
    < many-to-one name ="Category" column ="DICCATEGORY_ID" not-null ="true" lazy ="proxy" class ="Demo.HIS.Infrastructure.Core.DicCategory" />
    </ class >
    </ hibernate-mapping >

    具体配置含义这里不详细解释,自己去Google....

  6. 建立字典类DicCategory和字典项Dictionary的数据访问接口及实现
    接口:

     
        
    namespace Demo.HIS.Infrastructure.Core.Repositories
    {
    /// /字典类别的数据库访问接口
    public interface IDicCategoryRepository : IRepository < DicCategory >
    {

    }
    }

     

     
        
    namespace Demo.HIS.Infrastructure.Core.Repositories
    {
    // 字典项的数据库访问接口
    public interface IDictionaryRepository : IRepository < Dictionary >
    {

    }
    }

    实现:

     
        
    namespace Demo.HIS.Infrastructure.Repositories
    {
    public class DicCategoryRepositoryImpl : RepositoryNhbImpl < DicCategory > ,IDicCategoryRepository
    {
    }
    }

     
        
    namespace Demo.HIS.Infrastructure.Repositories.Data
    {
    public class DictionaryRepositoryImpl : RepositoryNhbImpl < Dictionary > , IDictionaryRepository
    {
    }
    }

     

到此我们就实现了NHibernate基本的数据库访问

2009122522180578.jpg

源码: HISDemo-3.rar

PowerDesigner 12可以打开的数据库建模文件:PhysicalDataModel_1.rar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值