• 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

  • 相关阅读:
    电子商务标准体系RosettaNet与Microsoft BizTalk Accelerator for RosettaNet 无为而为
    sharepoint进行Unit Test的一个方案 无为而为
    微软VSTS的新功能:WebTest要点 无为而为
    IT部门的几种生存模式分析 无为而为
    一个人出现问题可能是道德问题,但是很多人都有相同的问题就一定不是道德问题。 无为而为
    意大利人有过关了,不过要面对东道主德国队未必会有这么容易 无为而为
    记一次阿里云OSS的STS授权访问
    得到应用程序所在路径
    反射 运用
    GetEnumerator用法
  • 原文地址:https://www.cnblogs.com/legendxian/p/1631985.html
Copyright © 2020-2023  润新知