1. 程式人生 > >Entity Framework 三層架構--持久層使用封裝之實體模型

Entity Framework 三層架構--持久層使用封裝之實體模型

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>