Entity Framework 三層架構--持久層使用封裝之實體模型
阿新 • • 發佈:2019-02-20
Entity Framework的橫空出世確立了其在.net領域官方ORM中的霸主地位,給我們開發者帶來了福音,但是使用使用上還是有些不便捷的地方,尤其是在三層架構的專案中,在業務層不容許出現直接操作ObjectContext 的情況下,需要針對不同實體編寫不同DAO的工作是令人感到繁瑣的。於是封裝一個DaoTemplate類試圖通過泛型手段涵蓋所有可能的查詢封裝要解決幾個問題:
1、持久層用一個類DaoTemplate儘量涵蓋80%的查詢需求,也可以根據需要編寫子類進行擴充套件
2、業務層不容許直接操作ObjectContext物件,業務層只關注業務,可以呼叫DaoTemplate實現各種讀寫能力
3、業務層對持久層的多次呼叫要支援事務
4、業務層事務程式碼對於成員是透明的,程式設計師無需知道事務的存在,而只管在業務方法裡面編寫複雜的業務
我採用model first的思路,模型如下:
專案結構如下:
一些類的介紹:
下面這個類來自網路一位仁兄的部落格,實現的是對Expression<Func<T, bool>>這種Lambda表示式提供And和Or擴充套件方法以實現動態查詢中動態構造Lambda條件表示式的需要:
public static class PredicateExtensions { public static Expression<Func<T, bool>> True<T>() { return f => true; } public static Expression<Func<T, bool>> False<T>() { return f => false; } public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2) { var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>()); return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression), expression1.Parameters); } public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2) { var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>()); Expression<Func<T,bool>> lambda =Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters); return lambda; } }
下面這個類是分頁資訊類,封裝分頁的條件和結果:
namespace EFLabModelFirst.JT.Dao { /// <summary> /// 分頁資訊類 /// </summary> /// <typeparam name="T">分頁的實體型別</typeparam> /// <typeparam name="TKey">排序的屬性型別</typeparam> /// <typeparam name="TResult">投影結果型別</typeparam> [Serializable] public class PageInfo<T, TKey, TResult> { /// <summary> /// 條件表示式樹 /// </summary> public Expression<Func<T, bool>> Where { get; set; } /// <summary> /// 排序表示式樹 /// </summary> public Expression<Func<T,TKey>> Order { get; set; } private String _include=string.Empty; /// <summary> /// 要抓取的導航屬性 /// </summary> public string Include { get { return _include; } set { _include = value; } } /// <summary> /// 投影表示式樹 /// </summary> public Expression<Func<T,TResult>> Select { get; set; } private int _pageSize = 10; /// <summary> /// 頁大小 /// </summary> public int PageSize { get { return _pageSize; } set { _pageSize = value; } } private int _pageIndex = 1; /// <summary> /// 頁號 /// </summary> public int PageIndex { get { return _pageIndex; } set { _pageIndex = value; } } /// <summary> /// 總條數 /// </summary> public long RecordCount { get; set; } /// <summary> /// 總頁數 /// </summary> public long PageCount { get; set; } /// <summary> /// 分頁結果 /// </summary> public ICollection<TResult> List { get; set; } } }
下面是App.Config配置檔案,因為DaoTemplate是一個通用的類,一些引數需要配置化:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<!--連線字串的名稱-->
<add key="ConnectionStringKey" value="modelfirstEntities"/>
<!--實體容器的名稱-->
<add key="EntityContainerName" value="modelfirstEntities"/>
<!--物件上下文型別 value="物件上下文型別全名,程式集名稱"-->
<add key="ObjectContextType" value="EFLabModelFirst.modelfirstEntities,EFLabModelFirst"/>
</appSettings>
<connectionStrings>
<add name="modelfirstEntities" connectionString="metadata=res://*/ModelFirst.csdl|res://*/ModelFirst.ssdl|res://*/ModelFirst.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.\sqlexpress;Initial Catalog=modelfirst;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>