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

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

  1. RepositoryNhbImpl数据库访问基类代码:
    代码
    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. 一般在信息管理系统中我们都会做“字典管理”功能,以方便客户自己维护一些下拉选项,如下图所示:
  3. 根据上面的需求,我们需要创建两个业务对象:
    字典类别DicCategory,虽然上图中被我搞花了,但你依然可以看出他是一个树形结构:) 而且可以预见在我们的系统中将来肯定有不少类似的树形结构,所以我们建立一个表示树形结构的基类:
    代码
    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:

    代码
    /// <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:

    代码
    /// <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. 建立数据库表:

    可以看到表间关系是典型的一对多
    注:这里先给个数据建模工具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映射文件的生成操作为嵌入资源

    字典类别DicCategory的Xml:

    代码
    <?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:

    代码
    <?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基本的数据库访问

源码: HISDemo-3.rar

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

posted on 2009-12-25 11:57  传说中的弦哥  阅读(11009)  评论(11编辑  收藏  举报

导航