实战Angular2+web api增删改查 (一)

前端之家收集整理的这篇文章主要介绍了实战Angular2+web api增删改查 (一)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Angular2是一个前端开发框架,在引入ts之后使得我们这些C#开发者能够更快的熟悉该框架,angular2开发首先要知道这是一个SPA(单页应用),我们要摆脱以往的asp.net中的MVC模式的固有思路,angular2开发重点是组件(Component),所以开发之前尤其要能清楚这个概念。

在与angular2配合使用的后端(RestFul)我采用的是基于asp.net的web api2.0,这也是目前比较流行的一种方式。我在webapi开发中在数据层使用的是基于NHibernate的Repository+UnitWork模式,自然也会用到依赖注入,我选的依赖注入工具是AutoFac。在前端与后端的数据传递使用DTO,为了方便,使用的是AutoMapper做数据映射。下面从底层开始,以一个简单实例演示整个过程。

领域模型

在建模时曾考虑使用EF6,目前也有很多关于EF6的争议就是EF中实际已包含了Repository和UnitOfWork模式,那么在使用EF时就不必再使用这种模式了,为了能够熟练这种模式我选用了NHibernate作为ORM框架。

数据实体类

publicclassTGroup:EntityBase{

publicTGroup(){

Users=newList<TUser>();

}

publicvirtualstringID{get;set;}

publicvirtualstringGROUPNAME{get;set;}

publicvirtualdecimal?NORDER{get;set;}

publicvirtualstringPARENTID{get;set;}

publicvirtualDateTime?CREATED{get;set;}

publicvirtualstringGROUPTYPE{get;set;}

publicvirtualstringGROUPCODE{get;set;}

publicvirtualIList<TUser>Users{get;set;}

}

数据实体类都继承于EntityBase,EntityBase是一个空的类,目前没有任何属性方法,只是为了在使用Repositroy模式时方便,其实可以抽象出诸如ID这样的公共属性出来。

关系映射

  1. <?xmlversion="1.0"encoding="utf-8"?>
  1. <hibernate-mappingassembly="URS.Data"namespace="URS.Data.Model"xmlns="urn:nhibernate-mapping-2.2">
  1. <classname="TGroup"table="T_GROUP"lazy="true">
  1. <idname="ID"column="ID"/>
  1. <propertyname="GROUPNAME">
  1. <columnname="GROUPNAME"sql-type="VARCHAR2"not-null="false"/>
  1. </property>
  1. <propertyname="NORDER">
  1. <columnname="NORDER"sql-type="NUMBER"not-null="false"/>
  1. </property>
  1. <propertyname="PARENTID">
  1. <columnname="PARENTID"sql-type="VARCHAR2"not-null="false"/>
  1. </property>
  1. <propertyname="CREATED">
  1. <columnname="CREATED"sql-type="DATE"not-null="false"/>
  1. </property>
  1. <propertyname="GROUPTYPE">
  1. <columnname="GROUPTYPE"sql-type="VARCHAR2"not-null="false"/>
  1. </property>
  1. <propertyname="GROUPCODE">
  1. <columnname="GROUPCODE"sql-type="VARCHAR2"not-null="true"/>
  1. </property>
  1. <bagname="Users"inverse="true"cascade="all">
  1. <keycolumn="GROUPID"/>
  1. <one-to-manyclass="TUser"/>
  1. </bag>
  1. </class>
  1. </hibernate-mapping>

在实体类中就可以看出这是一个一对多关系,TGroup包含了一个TUser集合,所以在映射时使用的bag中描绘了这个一对多关系,这里需要说明的是我所使用的是oracle数据库

NHibernate配置

  1. <?xmlversion="1.0"encoding="utf-8"?>
  1. <hibernate-configurationxmlns="urn:nhibernate-configuration-2.2">
  1. <session-factory>
  1. <propertyname="connection.driver_class">NHibernate.Driver.OracleManagedDataClientDriver</property>
  1. <propertyname="connection.connection_string">UserId=urs;Password=urs;DataSource=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORA11G)))</property>
  1. <propertyname="show_sql">true</property>
  1. <propertyname="dialect">NHibernate.Dialect.Oracle10gDialect</property>
  1. <propertyname="query.substitutions">true1,false0,yes'Y',no'N'</property>
  1. <propertyname="current_session_context_class">call</property>
  1. <mappingassembly="URS.Data"/>
  1. </session-factory>
  1. </hibernate-configuration>

这是一个使用oracle的odp的连接配置,这个配置文件需要放在WebAPI解决方案下

Repository模式

IRepository接口

  1. publicinterfaceIRepository<TEntity>:IDependencywhereTEntity:EntityBase
  1. {
  1. TEntityGet(objectid);
  1. IList<TEntity>GetAll();
  1. voidAdd(TEntityentity);
  1. voidUpdate(TEntityentity);
  1. voidDelete(TEntityentity);
  1. voidDelete(objectid);
  1.  
  1.  
  1. }

这里的IRepository接口只提取了部分通用的CURD操作,这里需要注意的是该接口继承了IDependency,这是为了我们下面使用依赖注入的一个空接口,下面会说到这样的目的。

Repository基类

  1. publicclassNHRepositoryBase<TEntity>:IRepository<TEntity>whereTEntity:EntityBase
  1. {
  1. protectedvirtualISessionSession
  1. {
  1. get
  1. {
  1. returnSessionBuilder.GetCurrentSession();
  1. }
  1. }
  1. publicvirtualTEntityGet(objectid)
  1. {
  1. returnSession.Get<TEntity>(id);
  1.  
  1. }
  1. publicvirtualIList<TEntity>GetAll()
  1. {
  1. returnSession.CreateCriteria<TEntity>()
  1. .List<TEntity>();
  1. }
  1. publicvirtualvoidAdd(TEntityentity)
  1. {
  1. try
  1. {
  1. Session.Save(entity);
  1. }
  1. catch(Exceptionex)
  1. {
  1. throwex;
  1. }
  1. }
  1. publicvirtualvoidUpdate(TEntityentity)
  1. {
  1. try
  1. {
  1. Session.SaveOrUpdate(entity);
  1. }
  1. catch(Exceptionex)
  1. {
  1. throwex;
  1. }
  1. }
  1. publicvirtualvoidDelete(TEntityentity)
  1. {
  1. try
  1. {
  1. Session.Delete(entity);
  1. }
  1. catch(Exceptionex)
  1. {
  1. throwex;
  1. }
  1. }
  1. publicvirtualvoidDelete(objectid)
  1. {
  1. try
  1. {
  1. TEntityentity=this.Get(id);
  1. Session.Delete(entity);
  1. }
  1. catch(Exceptionex)
  1. {
  1. throwex;
  1. }
  1. }
  1. }

由于我们使用的是NHibernate,所以我们需要一个全局的ISession,SessionBuilder是我封装的一个类,用来处理ISession,保障一个应用中只有一个ISession实例。

业务Repository

  1. publicclassGroupRepository:NHRepositoryBase<TGroup>,IGroupRepository
  1. {
  1.  
  1. }

由于Repository基类中包含了通用的CURD操作,所以这个GroupRepository只需继承这个基类即可,如果还有其他操作或属性则再进一步抽象出IGroupRepository这里我还没打算加入其他操作所以IGroupRepository是个空的接口,以后也许会加入其他方法属性

UnitOfWork模式

unitofwork模式重点是处理事务,对变化的数据一次提交保证数据完整性。

IUnitOfWork接口

  1. publicinterfaceIUnitOfWork:IDisposable,IDependency
  1. {
  1. IRepository<TEntity>BaseRepository<TEntity>()whereTEntity:EntityBase;
  1. voidBeginTransaction();
  1. voidCommit();
  1. voidRollback();
  1. }

这个接口同样也继承了IDependency,也是为了后面的依赖注入。在这个接口中我还定义了一个IRepository<TEntity>的属性,这是一个能够根据实体类来获取其对应的Repository。

UnitOfWork实现

  1. publicclassNHUnitOfWork:IUnitOfWork
  1. {
  1. privateITransaction_transaction;
  1. privateHashtable_repositories;
  1. publicISessionSession
  1. {
  1. get
  1. {
  1. returnSessionBuilder.GetCurrentSession();
  1. }
  1. }
  1. publicNHUnitOfWork()
  1. {
  1.  
  1. }
  1. publicvoidBeginTransaction()
  1. {
  1. this._transaction=Session.BeginTransaction();
  1. }
  1. publicvoidCommit()
  1. {
  1. try
  1. {
  1. //committransactionifthereisoneactive
  1. if(_transaction!=null&&_transaction.IsActive)
  1. _transaction.Commit();
  1. }
  1. catch
  1. {
  1. //rollbackiftherewasanexception
  1. if(_transaction!=null&&_transaction.IsActive)
  1. _transaction.Rollback();
  1. throw;
  1. }
  1. //finally
  1. //{
  1. //Session.Dispose();
  1. //}
  1. }
  1. publicvoidRollback()
  1. {
  1. //try
  1. {
  1. if(_transaction!=null&&_transaction.IsActive)
  1. _transaction.Rollback();
  1. }
  1. //finally
  1. //{
  1. //Session.Dispose();
  1. //}
  1. }
  1. publicvoidDispose()
  1. {
  1. Session.Dispose();
  1. }
  1. publicIRepository<T>BaseRepository<T>()whereT:EntityBase
  1. {
  1. if(_repositories==null)
  1. _repositories=newHashtable();
  1. vartype=typeof(T).Name;
  1. if(!_repositories.ContainsKey(type))
  1. {
  1. varrepositoryType=typeof(NHRepositoryBase<>);
  1. varrepositoryInstance=
  1. Activator.CreateInstance(repositoryType
  1. .MakeGenericType(typeof(T)));
  1. _repositories.Add(type,repositoryInstance);
  1. }
  1. return(IRepository<T>)_repositories[type];
  1. }
  1. }

这里使用了反射创建Repository实例,这里是创建的通用基类型的Repository实例,好处就是当我们在业务逻辑层使用UnitOfWork时如果是通用的操作,则不用注入Repository了,否则可能要构造中可能要注入很多业务Repository,比较麻烦,当然如果不是通用操作的话,还是要注入的,下面会讲到。

业务逻辑层应用

  1. publicclassGroupService:IGroupService
  1. {
  1. privateIUnitOfWork_unitOfWork;
  1. privateIGroupRepository_groupRepository;
  1. publicGroupService(IUnitOfWorkunitOfWork,IGroupRepositorygroupRepository)
  1. {
  1. _unitOfWork=unitOfWork;
  1. _groupRepository=groupRepository;
  1. }
  1. publicIList<TGroup>GetAll()
  1. {
  1. IRepository<TGroup>repo=_unitOfWork.BaseRepository<TGroup>();
  1. returnrepo.GetAll();
  1. }
  1. publicTGroupGetByID(stringid)
  1. {
  1. IRepository<TGroup>repo=_unitOfWork.BaseRepository<TGroup>();
  1. returnrepo.Get(id);
  1. }
  1. publicvoidAdd(TGroupentity)
  1. {
  1. _unitOfWork.BeginTransaction();
  1. IRepository<TGroup>repo=_unitOfWork.BaseRepository<TGroup>();
  1. repo.Add(entity);
  1. _unitOfWork.Commit();
  1. }
  1. publicvoidDelete(stringid)
  1. {
  1. _unitOfWork.BeginTransaction();
  1. IRepository<TGroup>repo=_unitOfWork.BaseRepository<TGroup>();
  1. repo.Delete(id);
  1. _unitOfWork.Commit();
  1. }
  1. publicvoidUpdate(TGroupentity)
  1. {
  1. _unitOfWork.BeginTransaction();
  1. IRepository<TGroup>repo=_unitOfWork.BaseRepository<TGroup>();
  1. repo.Update(entity);
  1. _unitOfWork.Commit();
  1. }
  1. }

这里通过在构造函数中注入IUnitOfWorkIGroupRepository这里可以看到,由于在本例中使用的都是通用的数据CURD,所以实际上IGroupRepository并没有使用,而实际使用的是IUnitOfWork中创建的IRepository<TGroup>,由于这个例子比较简单,如果是由复杂业务逻辑的话,那么需要在_unitOfWork.BeginTransaction()到_unitOfWork.Commit()之间完成业务处理即可保障数据提交的一致性,如果这中间有异常,IUnitOfWork会回滚,这就意味着要么全部提交,要不都不提交。

  1. 这里的GroupService继承了IGroupServiceIGroupService也会继承IDependency下面将在WebApi解决方案中介绍AutoFac的依赖注入使用方法

猜你在找的Angularjs相关文章