我選擇在項目中采用Nhibernate+Spring.Net+Asp.Net + Jquery 來作為我的主要.Net技術,我的框架的設計借鑒了博客園博主 傳說中的弘哥博主的大量的技術思路 http://www.cnblogs.com/legendxian/ 結合了自己在實際項目中的經驗,下面介紹我選擇這套技術的思路和理由:
1.技術選擇Nhibernate理由:
對象關系映射技術(ORM)的最主要目的是為了解決關系數據庫與面向對象編程技術不匹配的阻抗問題,通常所說的面向對象的類往往都存在繼承和類間關系與數據庫的表不是—對應的,ORM 技術可屏蔽掉數據庫訪問的技術細節,讓我們更專注於業務和UI實現,另外不能強制要求客戶使用固定的數據庫產品,Nhibernate 很大程度上屏蔽了不同數據庫產品之間差異,使我們不必對不同數據庫產品寫具體實現,類庫設計的原則:高內聚,低耦合。
(1)系統結構類圖
1. 數據訪問層:
主要用NHibernate訪問數據庫,但也有可能去訪問其他模塊或系統的WebService,也有可能用Linq去訪問一些緩存(內存中的)數據。
2. 業務領域層:
所有與數據訪問無關的業務邏輯都應該內聚在這里,業務領域對象理論上應該是充血的,內聚自己的業務邏輯。但有一些業務邏輯在設計的時候涉及到了多個業務領域對象 ,我們很難決定放在哪個具體的業務對象里,所以我們有一個Service層來放這種業務邏輯。
3. 門面層:
把數據訪問接口,業務領域對象的業務邏輯,Service接口簡單的封裝一下成為Facade層接口供展示層UI或SOA層調用,這個層可以避免界面和數據庫的平凡的交互。
數據訪問層
{
T Load( string id);
T Get( string id);
IList<T> GetAll();
void SaveOrUpdate(T entity);
void Update(T entity);
void Delete( string id);
void PhysicsDelete( string id);
}
Repository.cs 數據訪問層采用Nhibernate 實現
using System;
using System.Linq;
using System.Text;
using Demo.HIS.FrameWork.DomainBase;
using NHibernate;
using NHibernate.Criterion;
using Demo.HIS.FrameWork.Repository.NHb;
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
}
}
業務領域層: IMenuRepository 菜單模塊業務領域邏輯
using System;
using System.Linq;
using System.Text;
namespace Demo.HIS.Infrastructure.Core.Authority.Repositories
{
public interface IMenuRepository : IRepository<MenuNode>
{
bool IsFieldExist( string fieldName, string fieldValue, string id);
IList<MenuNode> GetListByUserId( string userId);
IList<MenuNode> GetListByRoleId( string roleId);
/// <summary>
/// 獲取用戶常用菜單列表
/// <remarks> 排除用戶沒權限的菜單 </remarks>
/// </summary>
/// <param name="userId"> 用戶Id </param>
/// <returns></returns>
IList<MenuNode> GetUserFavoriteList( string userId);
}
}
門面層接口:IMenuFacade.cs 此處設計一個抽象的外觀類可以方便擴張和需求的變化
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Demo.HIS.FrameWork;
using Demo.HIS.FrameWork.DomainBase;
using Demo.HIS.Infrastructure.Core.Authority.Repositories;
using Demo.HIS.Infrastructure.Core.Authority;
namespace Demo.HIS.Infrastructure.Facade.Authority
{
public interface IMenuFacade : IDomainFacade
{
IList<MenuNode> GetAlllist();
bool IsFieldExist( string fieldName, string fieldValue, string id);
void SaveOrUpdate(MenuNode entity);
void Delete( string id);
MenuNode Get( string id);
MenuNode Load( string id);
IList<ActionPermission> QueryActionPlist( string query, int start, int limit, out long total);
IList<MenuNode> GetMenuListByRoleId( string roleId);
}
}
MenuFacadeImpl.cs 實現IMenuFacade.cs 對業務邏輯的封裝,便於界面的類的調用。
using System;
using System.Linq;
using System.Text;
using Demo.HIS.Infrastructure.Core.Authority.Repositories;
using Demo.HIS.Infrastructure.Core.Authority;
using Demo.HIS.FrameWork.DomainBase;
using Demo.HIS.Infrastructure.Core.Authority.Services;
namespace Demo.HIS.Infrastructure.Facade.Authority.Impl
{
public class MenuFacadeImpl : IMenuFacade
{
private readonly IMenuRepository MenuRepository;
private readonly IActionPermissionService ActionPermissionService;
public MenuFacadeImpl(IMenuRepository MenuRepository, IActionPermissionService ActionPermissionService)
{
this.MenuRepository = MenuRepository;
this.ActionPermissionService = ActionPermissionService;
}
#region IMenuFacade 成員
public IList<MenuNode> GetAlllist()
{
return MenuRepository.GetAll();
}
public bool IsFieldExist( string fieldName, string fieldValue, string id)
{
return MenuRepository.IsFieldExist(fieldName, fieldValue, id);
}
public void SaveOrUpdate(MenuNode entity)
{
MenuRepository.SaveOrUpdate(entity);
}
public void Delete( string id)
{
MenuRepository.Delete(id);
}
public MenuNode Get( string id)
{
return MenuRepository.Get(id);
}
public MenuNode Load( string id)
{
return MenuRepository.Load(id);
}
public IList<ActionPermission> QueryActionPlist( string query, int start, int limit, out long total)
{
return ActionPermissionService.QueryActionPlist(query,start,limit, out total);
}
public IList<MenuNode> GetMenuListByRoleId( string roleId)
{
return MenuRepository.GetListByRoleId(roleId);
}
#endregion
}
}
MenuRepositoryImpl.cs 業務領域邏輯具體實現
using System;
using System.Linq;
using System.Text;
using Demo.HIS.Infrastructure.Core.Authority.Repositories;
using Demo.HIS.Infrastructure.Core.Authority;
using Demo.HIS.FrameWork.Repository;
using Demo.HIS.FrameWork;
using Demo.HIS.FrameWork.DomainBase;
using Demo.HIS.FrameWork.Repository.Nhb;
namespace Demo.HIS.Infrastructure.Repositories.Authority
{
public class MenuRepositoryImpl : RepositoryNhbImpl<MenuNode>, IMenuRepository
{
public override void SaveOrUpdate(MenuNode entity)
{
if (IsFieldExist( " TreeCode ", entity.TreeCode, entity.Id, null))
throw new ExistException( " TreeCode ");
base.SaveOrUpdate(entity);
}
public override void Delete( string id)
{
var entity = Get(id);
if (IsChildForNotLeaf(id))
throw new ValidationException( " 所選項下面存在子項,無法刪除! ");
base.Delete(id);
}
#region IMenuRepository 成員
public bool IsFieldExist( string fieldName, string fieldValue, string id)
{
return base.IsFieldExist(fieldName, fieldValue, id, null);
}
public IList<MenuNode> GetListByUserId( string userId)
{
var query = Session.CreateQuery( @" select distinct t
from MenuNode as t
left join t.Roles as r
left join r.Persons p
where p.Id = :UserId and r.IsDelete = 0 and p.IsDelete = 0 and p.State = :PersonState and r.State=:RoleState order by t.Index asc ")
.SetString( " UserId ", userId)
.SetEnum( " PersonState ", PersonState.Normal)
.SetEnum( " RoleState ", RoleState.Normal);
return query.List<MenuNode>();
}
public IList<MenuNode> GetListByRoleId( string roleId)
{
var query = Session.CreateQuery( @" select distinct t
from MenuNode as t
left join t.Roles as r
where r.Id = :RoleId and r.IsDelete = 0 and r.State = :RoleState ")
.SetString( " RoleId ", roleId)
.SetEnum( " RoleState ", RoleState.Normal);
return query.List<MenuNode>();
}
public IList<MenuNode> GetUserFavoriteList( string userId)
{
var query = Session.CreateQuery( @" select distinct t
from MenuNode as t
left join t.FavoritedUsers u
left join u.Roles ur
where u.Id = :UserId and u.IsDelete = 0 and ur.IsDelete = 0 and u.State = :PersonState and ur.State = :RoleState
and exists (select m from MenuNode as m
left join m.Roles as mr
where mr.Id = ur.Id and t.Id = m.Id
and mr.IsDelete = 0 and mr.State = :RoleState) ")
.SetString( " UserId ", userId)
.SetEnum( " PersonState ", PersonState.Normal)
.SetEnum( " RoleState ", RoleState.Normal);
return query.List<MenuNode>();
}
#endregion
private bool IsChildForNotLeaf( string id)
{
var query = Session.CreateQuery( @" select count(*) from MenuNode as o where o.ParentId=:ParentId ")
.SetString( " ParentId ", id);
return query.UniqueResult< long>() > 0;
}
}
}
初學者在學習設計模式的過程中,很難理解設計模式在具體項目中如何應用,我非常喜歡設計模式,設計模式蘊含着軟件設計的很重要的思想,真正的要描述設計模式在實際項目中如何運用其實還是比較難的,主要是代碼會很多,建議初學者去看一些比較好的源代碼,去研究別人的設計思想,這樣會有很大的提高。
門面模式介紹 http://blog.csdn.net/lovelion/article/details/7798064