NET中小型企业项目开发框架系列(一个)
当时的前端,我们开发了基于Net一组结构sprint.NET+NHibernate+MVC+WCF+EasyUI等中小型企业级系统开发平台,如今把整个开发过程中的步步进展整理出来和大家分享,这个系列可能有点长。多多指导学习。
我们的底层开发平台是sprint.NET+NHibernate+MVC+WCF+EasyUI方式开发,顺便加点Spring.net注入的部分,当然我们最基本的关于权限设计、业务设计,而架构。咱们没有学过太复杂的架构。我们还是以最经常使用的MVC架构開始拓展
參考材料:
<<重构,改善既有代码的设计>>
<<.net应用架构设计原则,模式与实践>>
<<.net设计范式>>
<<代码整洁之道>>
首先我们要解说一下关于项目的搭建部分,我们的项目主要分6部分,业务逻辑层。数据訪问层,页面层,数据模型层以及一个公共类的部分,每层我们在这个基础上抽象了相应的接口,这样上一层仅仅须要对下一层,面向接口编程。同一时候有Spring.NET来管理层之间的关系。达到解耦的目的。
这里主要是:
业务逻辑层:
ICMSBLL:业务逻辑层接口
CMSBLL:业务逻辑层实现
抽象的数据底层封装(泛型)
ICommonSupportDAL:对公共的方法的抽象
CommonSupportDAL:公共方法的实现
数据訪问层:
ICMSDAL:数据訪问层接口
CMSDAL:数据訪问层实现
领域模型层:
Entity:这是EF建立的模型
集合类层:
Collections:封装了分页,对于集合类内部的增删改查,对集合类内部类的增删改查。
界面层:
ComplaintManageSystem:基本的MVC和LigerUI实现的界面部分
TZHSWEET.UI:关于MVC公共UI定义的部分
公共类库部分:
我们的目标是“0”增删改查的数据訪问层实现,主要是靠Nhibernate的定义通用的增删改从,然后其它类继承增删改查接口和对应的自己定义的子类的接口,实现拓展
首先,我们从曾经的写代码经验知道,我们的Dao主要是做增删改查等方面,我们就先定义一个公共方法的接口叫做ICommonSupportDAL,这个接口定义泛型增删改查
<span style="font-family:FangSong_GB2312;font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Entity;
namespace ICommonSupportDAL
{
public interface IRepository<T, TCollection> where T : class
{
#region 即时查询,通过ID查询
/// <summary>
/// 获取实体
/// </summary>
/// <param name="id">主键</param>
/// <returns>实体</returns>
T Get(object id);
#endregion
#region 延迟载入,通过ID查询
/// <summary>
/// 获取实体
/// </summary>
/// <param name="id">主键</param>
/// <returns>实体</returns>
T Load(T entity);
#endregion
#region 将数据持久化到数据库
/// <summary>
/// 插入实体
/// </summary>
/// <param name="entity">实体</param>
/// <returns>ID</returns>
object Save(T entity);
#endregion
#region 更新数据信息
/// <summary>
/// 改动实体
/// </summary>
/// <param name="entity">实体</param>
void Update(T entity);
#endregion
#region 若数据存在则改动信息,若不存在则插入
/// <summary>
/// 若数据存在则改动信息,若不存在则插入
/// </summary>
/// <param name="entity">实体</param>
void SaveOrUpdate(T entity);
#endregion
#region 删除实体
/// <summary>
/// 删除实体
/// </summary>
/// <param name="id">ID</param>
void Delete(T entity);
#endregion
#region 依据ID批量删除实体
//删除实体
//void Delete(T entity);
/// <summary>
/// 依据ID批量删除实体
/// </summary>
/// <param name="idList">ID集合</param>
void Delete(IList<T> idList);
#endregion
/// <summary>
/// 获取所有集合
/// </summary>
/// <returns>集合</returns>
//IQueryable<T> LoadAll(); /// <summary>
/// 分页获取所有集合
/// </summary>
/// <param name="count">记录总数</param>
/// <param name="pageIndex">页码</param>
/// <param name="pageSize">每页大小</param>
/// <returns>集合</returns>
//IQueryable<T> LoadAllWithPage(out long count, int pageIndex, int pageSize);
#region 无条件查询所有实体(单表查询)
/// <summary>
/// 无条件查询所有实体(单表查询)
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
TCollection LoadAll();
#endregion
#region 通过自己写where条件查询实体
/// <summary>
/// 通过自己写where条件查询实体
/// </summary>
/// <param name="whereSql"></param>
/// <returns></returns>
TCollection LoadAllByWhereSql(object whereSql);
#endregion
#region 依据某一条件字段删除
/// <summary>
/// 按条件删除
/// </summary>
/// <param name="columName">字段名</param>
/// <param name="columValue">字段值</param>
void DeleteAfterQuery(object columName, object columValue);
#endregion
#region 按一个条件查询(单表查询)
/// <summary>
/// 按一个条件查询
/// </summary>
/// <param name="columnName"></param>
/// <param name="columValue"></param>
/// <returns></returns>
TCollection getByCondition(object columnName, object columValue);
#endregion
#region 通过原生sql语句进行增删改查操作
/// <summary>
/// 通过原生sql语句进行增删改查操作
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
TCollection ExecuteOrQueryBySql(object sql);
#endregion
#region 多条件查询
/// <summary>
/// 多条件查询
/// </summary>
/// <returns></returns>
TCollection FindVer(QueryHelper<T> qh);
#endregion
#region 依据SQL语句查询
/// <summary>
/// 依据SQL语句查询
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
TCollection LoadAllBySql(string sql);
#endregion
#region 依据某一字段查询(多表查询)
/// <summary>
/// 依据某一字段查询(多表查询)
/// </summary>
/// <param name="columnName"></param>
/// <param name="columValue"></param>
/// <returns></returns>
TCollection LoadByCondition(object columnName, object columValue);
#endregion
}
} </span>
这层接口,大家可能觉得没什么必要,可是,这个接口很重要,这个接口保证了我们用Nhibernate一个抽象类实现增删改查的同一时候又添加了子类的自身扩展性.
接下来,就是Dao部分,我们须要非常谨慎的去设计,
首先我们要设计一个用Nhibernate实现的公共父类的CommonSupportDAL类,用它来实现增删改查,
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="color:#000000;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Spring.Data.NHibernate.Generic.Support;
using NHibernate;
using System.Linq.Expressions;
using System.Collections;
using ICommonSupportDAL;
using Entity;
using MCS.Library.Data.DataObjects;
using System.Reflection;
using Collections; namespace CommonSupportDAL
{ /// <summary>
/// 数据訪问层公共接口实现
/// </summary>
/// <typeparam name="T">实体泛型</typeparam>
public class RepositoryBase<T, TCollection> : HibernateDaoSupport, IRepository<T, TCollection>
where T : class
where TCollection : Collection<T, TCollection> ,new()
{ public String TEntityName;
public RepositoryBase()
{
String name = typeof(T).ToString();
this.TEntityName = name.Substring(name.LastIndexOf('.') + 1);
} #region 将实体持久化到数据库
/// <summary>
/// 将实体持久化到数据库
/// </summary>
/// <param name="entity">泛型实体</param>
/// <returns></returns>
public virtual object Save(T entity)
{
// this.HibernateTemplate.Find<T>("from UserInfo ");
try
{
this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto;
}catch(Exception ex)
{
}
Object TEntity = this.HibernateTemplate.Save(entity);
this.HibernateTemplate.Flush();
return TEntity; }
#endregion
#region 依据ID查询
/// <summary>
/// 依据ID查询
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual T Get(object id)
{ return this.HibernateTemplate.Get<T>(id); }
#endregion
#region 依据ID查询
/// <summary>
/// 依据ID查询
/// </summary>
/// <param name="id">实体ID</param>
/// <returns></returns>
public virtual T Load(T entity)
{
Object fild=null;
try
{
fild = entity.GetType().GetProperty("ID").GetValue(entity, null);
}
catch (Exception ex)
{
string typename = entity.GetType().ToString();
throw new Exception("请检查" + typename + "中是否存在主键ID!");
}
return this.HibernateTemplate.Load<T>(fild); }
#endregion
#region 查询全部实体信息
/// <summary>
/// 查询全部实体信息
/// </summary>
/// <returns></returns>
public virtual TCollection LoadAll()
{
TCollection tcollecton = new TCollection();
IList<T> list = this.HibernateTemplate.LoadAll<T>();
tcollecton.CopyFrom(list);
return tcollecton; }
#endregion
#region 依据条件查询实体集合信息(hql)
/// <summary>
/// 依据条件查询实体集合信息(hql)
/// </summary>
/// <returns></returns>
public virtual TCollection LoadAllByWhereSql(object whereSql)
{
TCollection tcollecton = new TCollection();
IList<T> list = this.HibernateTemplate.Find<T>("from " + TEntityName + " where " + whereSql);
tcollecton.CopyFrom(list);
return tcollecton; }
#endregion
#region 依据条件查询实体集合信息(sql)
/// <summary>
/// 依据条件查询实体集合信息(sql)
/// </summary>
/// <returns></returns>
public virtual TCollection LoadAllBySql(string sql)
{
TCollection tcollecton = new TCollection();
IList<T> list = this.HibernateTemplate.Find<T>(sql);
tcollecton.CopyFrom(list);
return tcollecton; }
#endregion
#region 更新实体信息
/// <summary>
/// 更新实体信息
/// </summary>
/// <param name="entity"></param>
public virtual void Update(T entity)
{
this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto;
this.HibernateTemplate.Update(entity);
this.HibernateTemplate.Flush();
}
#endregion
#region 依据ID删除信息
/// <summary>
/// 依据ID删除信息
/// </summary>
/// <param name="id"></param>
public void Delete(T entity)
{
this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto;
this.HibernateTemplate.Delete(entity);
this.HibernateTemplate.Flush(); } #endregion
#region 批量删除
/// <summary>
/// 批量删除
/// </summary>
/// <param name="idList"></param>
public virtual void Delete(IList<T> idList)
{ foreach (object item in idList)
{
this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto;
this.HibernateTemplate.Delete(item);
this.HibernateTemplate.Flush(); }
}
#endregion #region 按条件删除
/// <summary>
///按条件删除
/// </summary>
/// <param name="columName"></param>
/// <param name="columValue"></param>
public virtual void DeleteAfterQuery(object columName, object columValue)
{ IList<T> list = this.HibernateTemplate.Find<T>("from " + TEntityName + " u where u." + columName + " =?", new object[] { columValue }); //在运行删除
foreach (object t in list)
{
this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto;
this.HibernateTemplate.Delete(t);
this.HibernateTemplate.Flush(); } }
#endregion
#region 保存后更新
/// <summary>
/// 保存后更新
/// </summary>
/// <param name="entity"></param>
public virtual void SaveOrUpdate(T entity)
{
this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto;
this.HibernateTemplate.SaveOrUpdate(entity);
this.HibernateTemplate.Flush();
}
#endregion //#region
///// <summary>
///// 依据条件查询实体集合信息--sql语句,不推荐使用,会产生sql注入
///// </summary>
///// <returns></returns>
//public virtual IList<T> getBywhereSql(string wheresql)
//{ // IList<T> list = this.HibernateTemplate.Find<T>("from " + TName + " where " + wheresql);
// return list;
//}
//#endregion //#region //#endregion
///// <summary>
///// 依据条件查询实体集合信息--sql语句,不推荐使用。会产生sql注入
///// </summary>
///// <returns></returns>
//public virtual IList<T> getBySql(string sql)
//{ // IList<T> list = this.HibernateTemplate.Find<T>(sql);
// return list;
//}
#region 通过一个条件查询(单表查询)
/// <summary>
/// 通过一个条件查询(单表查询)
/// </summary>
/// <param name="columName">属性名</param>
/// <param name="columValue">属性值</param>
/// <returns></returns>
public virtual TCollection getByCondition(object columnName, object columValue)
{
TCollection tcoll = new TCollection();
//比方验证username。仅仅须要传入Name属性的名称和值就可以;
//这个Name是相应的实体的属性名称,非数据库字段名。例getByCondition("Name","11");
IList<T> list = this.HibernateTemplate.Find<T>("from " + TEntityName + " u where u." + columnName + " =? ", new object[] { columValue });
tcoll.CopyFrom(list);
return tcoll;
}
#endregion
#region 通过一个条件查询(多表查询)
/// <summary>
/// 通过一个条件查询(单表查询)
/// </summary>
/// <param name="columName">属性名</param>
/// <param name="columValue">属性值</param>
/// <returns></returns>
public virtual TCollection LoadByCondition(object columnName, object columValue)
{
TCollection tcoll = new TCollection();
//比方验证username,仅仅须要传入Name属性的名称和值就可以;
//这个Name是相应的实体的属性名称。非数据库字段名。例getByCondition("Name","11");
IList<T> list = this.HibernateTemplate.Find<T>("from " + TEntityName + " u where u." + columnName + " =?", new object[] { columValue });
tcoll=this.LoadById(list);
return tcoll;
}
#endregion
#region 通过原生sql语句进行增删改查操作
/// <summary>
/// 通过原生sql语句进行增删改查操作
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
public TCollection ExecuteOrQueryBySql(object sql)
{
TCollection tcollecton = new TCollection();
ISQLQuery sqlQuery = this.HibernateTemplate.SessionFactory.GetCurrentSession().CreateSQLQuery(sql.ToString()).AddEntity(typeof(T));
tcollecton.CopyFrom(sqlQuery.List<T>());
return tcollecton;
}
#endregion
#region 多条件查询
/// <summary>
/// 多条件查询
/// </summary>
/// <returns></returns>
public TCollection FindVer(QueryHelper<T> qh)
{
// QueryHelper<T> qh = new QueryHelper<T>("u");
//return qh; // 參数列表
IList<Object> parameters = qh.getParameters(); // 查询本页的数据列表
IQuery listQuery = this.HibernateTemplate.SessionFactory.GetCurrentSession().CreateQuery(qh.getListQueryHql()); // 创建查询对象
if (parameters != null)
{ // 设置參数
for (int i = 0; i < parameters.Count; i++)
{
listQuery.SetParameter(i, parameters[i]);
}
} listQuery.List();
TCollection tcollection = new TCollection();
IList<T> list = listQuery.List<T>();
tcollection.CopyFrom(list);
return tcollection;
}
#endregion
#region 分页查询
/// <summary>
/// 分页查询
/// </summary>
/// <param name="tcollection"></param>
/// <returns></returns>
public TCollection LoadAllByPage(TCollection tcollection)
{ IQuery query = this.HibernateTemplate.SessionFactory.OpenSession().CreateQuery("from "+typeof(T).ToString());
query.SetFirstResult((tcollection.PageNum - 1) * tcollection.PageSize);
query.SetMaxResults(tcollection.PageSize);
IList list = query.List();
TCollection tcoll = new TCollection();
tcoll.TotalRecords=this.LoadAll().Count();
IEnumerator en = list.GetEnumerator();
while (en.MoveNext())
{
tcoll.Add((T)en.Current);
}
//tcoll.CopyFrom(list);
return tcoll;
}
#endregion
#region 通过多个ID查询
/// <summary>
/// 通过多个ID查询
/// </summary>
/// <param name="entity">包括ID信息的实体集合</param>
/// <returns>集合信息</returns>
public TCollection LoadById(IList<T> entity) {
IEnumerator en = entity.GetEnumerator();
IList<object> IDlist = new List<object>();
while (en.MoveNext())
{
Object fild = null;
try
{
fild = en.Current.GetType().GetProperty("ID").GetValue(en.Current, null);
}
catch (Exception ex)
{
string typename = en.Current.GetType().ToString();
throw new Exception("请检查" + typename + "中是否存在主键ID!");
} IDlist.Add("'"+fild+"'");
} IQuery query = this.HibernateTemplate.SessionFactory.OpenSession().CreateQuery("from " + TEntityName + " u where u.ID in (" +string.Join(",",IDlist.ToArray())+")");
// IQuery query = this.HibernateTemplate.SessionFactory.OpenSession().CreateQuery("from " + TEntityName + " u where u.ID in ('05221ff5-b491-4590-86bb-f5e275c6fd83','10df07ac-98ae-41f8-bcde-c4f48ec931f4','14c33f83-3be7-4162-8ace-8ef2e3677402','29780cc4-d7d8-4982-b8b7-ee63320da1d8','299ad880-06e3-48a3-80ca-570b8a557c42','7662b072-42a7-45fc-b11b-93efc844e5cd','87c26a14-56f2-4a57-9c99-e55f55ba6cdd','87c73291-591b-431f-b0fe-e73e15a490cf','917f9354-29e2-44b0-ad58-e2d8a0dd7670','9de57d2d-b4f8-4c56-9ce6-66673f42413d','a0e0cb9a-e8e4-4164-a021-cbcb61a8ea30','c6c239bf-6089-4c7c-983c-8ca479c360d5','c996d768-c9f9-4575-9268-4cfcf92fd038','ca09c55e-0a8d-4241-a364-74f1bdb60c32','da34ebae-11a7-4cfc-9772-b5e049768fe7','e5ee288e-8c5d-46bc-8c77-34b8c45750c1')"); IList list= query.List();
TCollection tc= new TCollection();
IEnumerator enumer=list.GetEnumerator();
while(enumer.MoveNext())
{
tc.Add((T)enumer.Current);
}
return tc;
}
#endregion
} }</span>
</span>
接下来我们的工作量就小了,我们能够看到成果了,我们接下来的实现,仅仅须要继承上面这个RepositoryBase和IRepository的部分就能够非常轻松的实现,子类的增删改查以及子类的扩展了.
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="color:#000000;"> public interface ICaseAssignEntityRepository:IRepository<CaseAssignEntity,CaseAssignEntityCollection>
{
}</span></span>
<span style="font-family:FangSong_GB2312;font-size:18px;">namespace CMSDAL.AnJianLuRu
{
public class CaseAssignEntityRepository : RepositoryBase<CaseAssignEntity, CaseAssignEntityCollection>, ICaseAssignEntityRepository
{
}
}</span>
大家看到继承了两个一个是RepositoryBase父类。一个是ICaseAssignEntityRepository自己的业务逻辑接口(实现了子类的拓展,比方在某个类中想要加入这个类特有的方法。仅仅须要在自己的接口中填写就可以)。通过这个继承体系保证了我们在实现增删改查的同一时候外放一个接口保证扩展性.
继承系列图:
总结
这样我们的数据訪问层,非常轻松的实现了,基本上代码量非常少,增删改查部分差点儿"0"代码,都是泛型的父类实现了.抽象、继承、泛型、托付、容器等等大大提高了代码的复用性。
-----一切来源于抽象。
今天就解讲到这里,接下来给大家解说Collection的封装与抽象。期待!
版权声明:本文博客原创文章,博客,未经同意,不得转载。
NET中小型企业项目开发框架系列(一个)的更多相关文章
- 《HiWind企业快速开发框架实战》(2)使用HiWind创建自己的项目
<HiWind企业快速开发框架实战>(2)使用HiWind创建自己的项目 关于HiWind HiWind企业快速开发框架,是基于.NET+EasyUi(支持各种前端扩展,后面将扩展Boot ...
- Linux运维企业架构项目实战系列
Linux运维企业架构项目实战系列 项目实战1—LNMP的搭建.nginx的ssl加密.权限控制的实现 项目实战2—LVS.nginx实现负载均衡系列2.1 项目实战2.1—实现基于LVS负载均衡集群 ...
- 今天介绍一下自己的开源项目,一款以spring cloud alibaba为核心的微服务架构项目,为给企业与个人提供一个零开发基础的微服务架构。
LaoCat-Spring-Cloud-Scaffold 一款以spring cloud alibab 为核心的微服务框架,主要目标为了提升自己的相关技术,也为了给企业与个人提供一个零开发基础的微服务 ...
- 《HiWind企业快速开发框架实战》(0)目录及框架简介
<HiWind企业快速开发框架实战>(0)目录及框架简介 本系列主要介绍一款企业管理系统快速开发框架,该框架旨在快速完成企业管理系统,并实现易维护可移植的目标. 使用逐个系统模块进行编码的 ...
- 《HiWind企业快速开发框架实战》(3)使用HiWind创建和管理菜单
<HiWind企业快速开发框架实战>(3)使用HiWind创建和管理菜单 关于HiWind HiWind企业快速开发框架,是基于.NET+EasyUi(支持各种前端扩展,后面将扩展Boot ...
- ABP(现代ASP.NET样板开发框架)系列之18、ABP应用层——权限验证
点这里进入ABP系列文章总目录 ABP(现代ASP.NET样板开发框架)系列之18.ABP应用层——权限验证 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目 ...
- ABP(现代ASP.NET样板开发框架)系列之20、ABP展现层——动态生成WebApi
点这里进入ABP系列文章总目录 ABP(现代ASP.NET样板开发框架)系列之20.ABP展现层——动态生成WebApi ABP是“ASP.NET Boilerplate Project (ASP.N ...
- 《HiWind企业快速开发框架实战》(1)框架的工作原理
<HiWind企业快速开发框架实战>(1)框架的工作原理 1.HiWind架构 HiWind的基本架构如下: 持久层部分:同时为框架本身的业务服务,也为开发人员的自定义业务服务. 逻辑层: ...
- RDIFramework.NET — 基于.NET的快速信息化系统开发框架 — 系列目录
RDIFramework.NET — 基于.NET的快速信息化系统开发框架 — 系列目录 RDIFramework.NET,基于.NET的快速信息化系统开发.整合框架,给用户和开发者最佳的.Net框架 ...
随机推荐
- javascript它【蛇系列】第一弹:简单的蛇实现
参考博客:http://blog.csdn.net/sunxing007/article/details/4187038 上面的博客是一个参考,竟第一次做.真让自己盲人摸象做不出来. 只是我在其上做了 ...
- 编译v8引擎
本机环境是win7+vs2010(本来想用2012的,但是发现默认的项目是2010的) 1.首先下载V8的源码 安装好svn,并在cmd下能使用svn help: svn下载地址(安装包):http: ...
- Android编程心得-图片自适应心得
在Android 的开发过程中,我们知道存放图片资源的文件夹是drawable,与它类似的名字的文件夹drawble-hdpi,drawable-ldpi,drawable-mdpi,drawable ...
- Linux SSH端口转发
SSH端口转发分为两种,一种是本地端口转发,又称为本地SSH隧道.一直是远程端口转发.SSH端口转发,还必须指定数据传送的目标主机,从而形成点对点的端口转发. 本地端口转发 假定有三台主机A. ...
- ASPF简介
ASPF是一种应用层状态检测技术,它通过与NAT和ALG等技术的组合应用,实现对应用层协议状态的处理和检测. 1.1 产生背景 随着计算机技术和网络技术的普及,网络安全问题也越来越得到关注.防火墙作 ...
- redis加入到Windows 服务
1.cmd命令 安装命令: redis-server.exe --service-install redis.windows.conf --loglevel verbose 卸载命令: redi ...
- 使用Google Roads API抓取道路信息(java实现)
Google Roads API提供了强大的道路获取接口,用户仅仅需调用对应的API就能够获取对应区域的道路坐标以及道路的限速信息. 详细的调用方法例如以下: https://roads.google ...
- ServiceProvider实现
ServiceProvider实现揭秘 [总体设计 ] 本系列前面的文章我们主要以编程的角度对ASP.NET Core的依赖注入系统进行了详细的介绍,如果读者朋友们对这些内容具有深刻的理解,我相信你们 ...
- Eclipse常用设置汇总
设置编码: . 设置字体: 依次展开 Window->Preferences->Java->Code Style->Formatter 在右边窗口中找到Edit ·找到Lin ...
- HUNNU11354:Is the Name of This Problem
http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11354&courseid=0 Problem des ...