上篇文章簡單的介紹了一下,我的一個開發框架。看的人還不少,多謝大家的關注,我繼續介紹一下,模塊和模塊之間是怎么組織起來的。
Data模塊:
該模塊主要完成對數據的操作,采用倉儲模式實現,在核心模塊(Core.Data)中定義操作接口和基礎類. 主要的接口有IRepository,IUnitOfWork,IDbCnnFactory。
所有的數據庫操作都是針對實體進行的,一個實體在數據庫中對應一個比,目前為了簡化操作,不考慮實體關聯的操作。這樣更加容易理解,更容易上手。
一、接口的定義
1、IRepository接口,最基本、最重要的接口。通過它完成實體類的增刪改查的操作。
IRepository/// <summary>
/// Interface IRepository
/// </summary>
/// <typeparam name="T">業務實體</typeparam>
/// <typeparam name="Tid">業務實體的主鍵類型</typeparam>
public interface IRepository<T, Tid> where T : EntityBase<Tid>, new()
{
/// <summary>
/// 添加數據
/// </summary>
/// <param name="entity">The entity.</param>
void Add(T entity);
/// <summary>
/// 批量添加數據
/// </summary>
/// <param name="entities">The entities.</param>
void Add(IEnumerable<T> entities);
/// <summary>
/// 更新數據
/// </summary>
/// <param name="entity">The entity.</param>
void Update(T entity);
/// <summary>
/// 批量更新數據
/// </summary>
/// <param name="entities">The entities.</param>
void Update(IEnumerable<T> entities);
/// <summary>
/// Delete item
/// </summary>
/// <param name="entity">The entity.</param>
void Delete(T entity);
/// <summary>
/// 批量刪除數據
/// </summary>
/// <param name="entities">The entities.</param>
void Delete(IEnumerable<T> entities);
/// <summary>
/// 根據主鍵刪除數據
/// </summary>
/// <param name="id">The id.</param>
void DeleteByID(object id);
/// <summary>
/// 刪除符合條件的實體
/// </summary>
/// <param name="filter"></param>
void Delete(Expression<Func<T, bool>> filter);
/// <summary>
/// 根據主鍵批量刪除數據
/// </summary>
/// <param name="ids">The ids.</param>
void DeleteByIDs(IEnumerable<Tid> ids);
/// <summary>
/// 通過ID讀取數據
/// </summary>
/// <param name="id">The id.</param>
/// <returns>`0.</returns>
T GetEntityByID(object id);
/// <summary>
/// 獲得符合條件的第一個實體
/// </summary>
/// <param name="filter"></param>
T GetEntity(Expression<Func<T, bool>> filter);
/// <summary>
/// 開始一個工作單元
/// </summary>
/// <returns>IUnitOfWork.</returns>
IUnitOfWork OpenUnitOfWork();
/// <summary>
/// 讀取全部數據
/// </summary>
/// <returns>List of selected elements</returns>
IEnumerable<T> GetEntities();
/// <summary>
/// 根據過濾條件讀取數據
/// </summary>
/// <param name="filter">過濾條件</param>
/// <returns>List of selected elements</returns>
IEnumerable<T> GetEntities(Expression<Func<T, bool>> filter);
/// <summary>
/// 根據過濾條件和排序條件讀取數據
/// </summary>
/// <typeparam name="S"></typeparam>
/// <param name="filter">過濾條件</param>
/// <param name="orderByExpression">排序條件</param>
/// <param name="ascending">是否為正序</param>
/// <returns>IEnumerable{`0}.</returns>
IEnumerable<T> GetEntities<S>(Expression<Func<T, bool>> filter,
Expression<Func<T, S>> orderByExpression, bool ascending = true);
/// <summary>
/// 分頁讀取數據
/// </summary>
/// <param name="pageIndex">頁號</param>
/// <param name="pageSize">每頁大小</param>
/// <returns>List of selected elements</returns>
PageResult<T> GetPagedEntities(int pageIndex, int pageSize);
/// <summary>
/// 分頁讀取數據
/// </summary>
/// <param name="filter">過濾條件</param>
/// <param name="pageIndex">頁號</param>
/// <param name="pageSize">每頁大小</param>
/// <returns>List of selected elements</returns>
PageResult<T> GetPagedEntities(Expression<Func<T, bool>> filter, int pageIndex, int pageSize);
/// <summary>
/// 分頁讀取數據
/// </summary>
/// <typeparam name="S"></typeparam>
/// <param name="filter">過濾條件</param>
/// <param name="orderByExpression">排序條件</param>
/// <param name="ascending">是否正序</param>
/// <param name="pageIndex">頁號</param>
/// <param name="pageSize">每頁大小</param>
/// <returns>List of selected elements</returns>
PageResult<T> GetPagedEntities<S>(Expression<Func<T, bool>> filter, Expression<Func<T, S>> orderByExpression, bool ascending, int pageIndex, int pageSize);
/// <summary>
/// 分頁讀取數據
/// </summary>
/// <param name="filter">sql過濾條件</param>
/// <param name="pageIndex">頁號</param>
/// <param name="pageSize">每頁大小</param>
/// <returns>PageResult{`0}.</returns>
PageResult<T> GetPagedEntities(string filter, int pageIndex, int pageSize);
/// <summary>
/// 分頁讀取數據
/// </summary>
/// <param name="filter">sql過濾條件</param>
/// <param name="orderby">sql排序字段</param>
/// <param name="pageIndex">頁號</param>
/// <param name="pageSize">每頁大小</param>
/// <returns>PageResult{`0}.</returns>
PageResult<T> GetPagedEntities(string filter, string orderby, int pageIndex, int pageSize);
}
2、其中實體類必須繼承EntityBase<Tid>或 EntityBase 類,TId 是指ID的類型,每個實體必須有個主鍵Id,
EntityBase [Serializable]
public class EntityBase<Tid>
{
/// <summary>
/// 唯一主鍵
/// </summary>
/// <value>The id.</value>
public Tid Id { get; set; }
#region Override
/// <summary>
/// <see cref="M:System.Object.GetHashCode"/>
/// </summary>
/// <returns><see cref="M:System.Object.GetHashCode"/></returns>
public override int GetHashCode()
{
if (this.Id.Equals(null))
{
return base.GetHashCode();
}
else
return this.Id.GetHashCode() ^ 31;
}
/// <summary>
/// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
/// </summary>
/// <param name="obj">與當前的 <see cref="T:System.Object" /> 進行比較的 <see cref="T:System.Object" />。</param>
/// <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj)
{
if (obj == null || !(obj is EntityBase<Tid>))
return false;
if (Object.ReferenceEquals(this, obj))
return true;
EntityBase<Tid> item = (EntityBase<Tid>)obj;
return item.Id.Equals(this.Id);
}
/// <summary>
/// Implements the ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(EntityBase<Tid> left, EntityBase<Tid> right)
{
if (Object.Equals(left, null))
return (Object.Equals(right, null)) ? true : false;
else
return left.Equals(right);
}
/// <summary>
/// Implements the !=.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(EntityBase<Tid> left, EntityBase<Tid> right)
{
return !(left == right);
}
#endregion
}
3、IDbCnnFactory接口主要完成數據庫連接的維護工作
IDbCnnFactory /// <summary>
/// Interface IDbCnnFactory
/// </summary>
public interface IDbCnnFactory
{
/// <summary>
/// 默認的數據庫鍵值,多數據庫時用
/// </summary>
string DefaultDbKey { get; }
/// <summary>
/// 數據庫提供者
/// </summary>
/// <value>The db provider.</value>
string DbProvider { get; }
/// <summary>
/// 打開一個數據庫連接
/// </summary>
/// <returns>IDbConnection.</returns>
IDbConnection OpenConnection(string dbKey="");
/// <summary>
/// 創建一個數據庫連接
/// </summary>
/// <returns>IDbConnection.</returns>
IDbConnection CreateConnection(string dbKey="");
}
4、IUnitOfWork接口主要實現將多個數據庫操作組合成一個工作單元, 對數據庫來說就是一個事務。
IUnitOfWork /// <summary>
/// Interface IUnitOfWork
/// </summary>
public interface IUnitOfWork : IDisposable
{
/// <summary>
/// 提交更改
/// </summary>
void Commit();
/// <summary>
/// Begins the transition.
/// </summary>
/// <returns>IDisposable.</returns>
IDisposable BeginTransition();
/// <summary>
/// 撤銷更改
/// </summary>
void Rollback();
}
另外還有幾個輔助的接口,同樣是在Core.Data中定義
ISqlRepository:類似於以前的SQLHelper類,它里面只是定義了一些執行sql的方法。
ITableManager :用於數據表的維護。新建、刪除、重建表操作。
PageResult<TEntity>:分頁結果類,主要保存 共有多少頁,當前第幾頁,以及當前頁的數據。
UnitOfWork類:IUnitOfWork接口的實現類。
IStatRepository:簡單的數據統計.
二、接口的實現
Data.Oracle是針對Oracle數據庫的一個實現。

Repository類實現了一下接口一個是默認ID類型的,一個是可自定義ID類型的.
public class Repository<TEntity, Tid> : IRepository<TEntity, id>,IStatRepository<TEntity,Tid>,ISqlRepository
where TEntity : EntityBase<Tid>, new()
public class Repository<TEntity> : Repository<TEntity, Guid>, IRepository<TEntity>, IStatRepository<TEntity>
where TEntity : EntityBase, new()
OracleDbCnnFactory 實現就比較簡單了,和寫ADO.Net一樣.唯一注意的就是增加了MEF的導出標簽
[Export(typeof(IDbCnnFactory))] ,MEF的使用,園子里有很多好的文章,我就不班門弄斧了
三、接口的使用
比如我設計了一個菜單類,屬性主要有顯示的標題、關鍵字、序號等。
//獲得菜單類操作的Repository
var rep = ApplicationEx.Container.GetRepository<MenuInfo>();
//查詢所有可用的菜單,並排序
var ens= rep.GetEntities(t => t.Enable == true).OrderBy(t=>t.PIndex);
返回的是 IEnumerable<MenuInfo>
關於ApplicationEx類,我們后面會介紹到。
通過以上這些接口,我相信90%的數據庫操作,都能滿足。如果你的系統對性能要求比較高的話,我建議直接寫sql+ADO.Net寫,執行效率會更好,也好優化。
我這樣設計也考慮到Web程序的應用,畢竟程序能在web、手機上實現的都會移植過去,單機的項目會越來越少。