其實我對微軟出的Linq to Sql,以及Linq to Entity這兩個產品興趣都不大,不太喜歡那種開發模式,主要原因如下:

    1:自動生成的那堆代碼,不利於平時的分層模式,將實體以及存儲邏輯混合在一起總覺的不是那麼回事;

    2:對於編寫測試用例不是那麼友好,全部邏輯都在一起,無法拆分測試,比如只想測試代碼邏輯,不需要連接真正的數據庫等。

    3:在排除程序BUG時,還是習慣於看直觀的SQL,這樣在數據庫中調試起來更加容易些,可能是個人習慣問題;

    4:據説性能上存在一定缺陷,本人並未測試過,道聽途説而已。


    之所以這次想嘗試一次,主要基於兩點:首先我現在接手的一個項目是用EF編寫的,其次就是EF 4.2能夠將原來混合在一起的代碼給分離開,説的官方點,這個分離功能叫POCO,英文全名是Plain Old CLR Object,翻譯成中文是簡單傳統的CLR對象。總之最新的EF允許開發人員手工編寫更多代碼,不再一味的依賴代碼自動生成。


    第一:如何安裝EF 4.2?


    我電腦上原來安裝的是EF 4.0,這次選擇的是通過NuGet方式安裝。

    1:首先從VS菜單上選擇工具,然後選擇擴展管理,如下圖。

      

pfx 轉換pem_EF


   

      2:在彈出框的左側選擇Online,然後在右上角搜索Nuget,最後進行安裝。

,

      

pfx 轉換pem_pfx 轉換pem_02

    3:安裝NUGET後,我們在工程的引用中點擊右鍵,就會多出一項來,如下所示。

      

pfx 轉換pem_pfx 轉換pem_03

 

 

    4:添加EF引用。點擊上圖中的最後一項,搜索EntityFramework,就會看到最新的EF了,選擇進行添加即可。

      

pfx 轉換pem_UI_04

 

    第二:創建EF程序。
 
    我採用的是最早的模式,即先有數據庫,然後再有程序的模式,程序分了如下幾層:

 

     

pfx 轉換pem_UI_05

 

    1:ModelFirstSample.DAL,這是數據層,用於存放與數據庫打交道的邏輯;
      先按正常流程添加一個ADO.NET Entity Data Model,按步就班,一步一步下來就行。這樣會生成一個.edmx的文件。

 

    

pfx 轉換pem_pfx 轉換pem_06

 

 

     然後打開edmx文件,點擊右鍵選擇添加代碼生成項,在彈出的菜單中選擇Db context那項,接下來會生成PersonModel.tt,PersonModel.Context.tt兩文件,對應的edmx下面的自動生成的代碼已經為空了。    

 

      

pfx 轉換pem_pfx 轉換pem_07

 

    2:ModelFirstSample.Model,實體層,將EF生成的.edmx,.tt文件放在這,與存儲邏輯分離;
      將第一步生成的PersonModel.edmx,PersonModel.tt添加到工程下面,同時刪除原文件,這樣就實現了實體層與存儲邏輯的分離。
    3:ModelFirstSample.BLL,業務邏輯層,不用多説;
    4:ModelFirstSample.Service,服務層,對於業務邏輯層的進一步包裝;
    5:ModelFirstSample.ConsoleApp,UI層。

    第三:EF中的開發模式之Repository。

    在實際項目中,如果希望能夠對存儲邏輯有一定的控制,於是就有了repository模式的出現,也就是對原始存儲邏輯的一種封裝。
    1:在接口層中創建一個通用的存儲接口IRepository<T>,便於邏輯複用。

public interface IRepository<T> where T : class, new()

    {

        T Create();

        T Update(T entity);

        T Insert(T entity);

        void Delete(T entity);

        T Find(params object[] keyValues);

        List<T> FindAll();

    }

    2:在DAL層中創建一個實現了IRepository<T>接口的RepositoryBase<T>基類,主要的就是需要提供一個DbContext,基本思想就是利用DbContext的Set<T>構造的類型來提供封裝,這裏就不做多的説明了,我這裏為了簡單,使用了默認構造方法,FacePerfEntities是添加edmx時生成的類。
   

pfx 轉換pem_EF_08

pfx 轉換pem_List_09

View Code

public class RepositoryBase<T> : IRepository<T> where T : class,new()

    {

        public DbContext context;


        public RepositoryBase(DbContext _context)

        {

            this.context = _context;

        }

        public RepositoryBase()

        {

            this.context = new FacePerfEntities();

        }

        #region IRepository<T> 成員


        public T Create()

        {

            return context.Set<T>().Create();

        }


        public T Update(T entity)

        {

            if (context.Entry<T>(entity).State == EntityState.Modified)

                context.SaveChanges();

            return entity;

        }


        public T Insert(T entity)

        {

            context.Set<T>().Add(entity);

            context.SaveChanges();

            return entity;

        }


        public void Delete(T entity)

        {

            context.Set<T>().Remove(entity);

            context.SaveChanges();

        }


        public T Find(params object[] keyValues)

        {

            return context.Set<T>().Find(keyValues);

        }


        public List<T> FindAll()

        {

            return context.Set<T>().ToList();

        }


        #endregion

    }

    3:在接口層中創建一個關於員工的接口:IEmployeeRepository<T>
   

public  interface IEmployeeRepository<T>

    {

       List<T> SearchEmployee();


    }

 

    4:在業務邏輯層中創建關於員工的專用類:EmployeeRepositoryBLL。
   

public class EmployeeRepositoryBLL : IEmployeeRepository<Employee>

    {

        EmployeeRepository repository = new EmployeeRepository();

        public List<Employee> SearchEmployee()

        {

            return repository.FindAll();

        }


    }

 

    5:在服務層中創建員工的服務類,由於這只是測試用,所以服務類起的作用並不明顯,至於為什麼有服務層,是為了將UI層與業務邏輯層分離等等眾多原因。

pfx 轉換pem_EF_08

pfx 轉換pem_List_09

View Code 
public  class EmployeeRepositoryService

    {

       EmployeeRepositoryBLL repositoryEmployee=null  ;

       public EmployeeRepositoryService()

       {

          repositoryEmployee = new EmployeeRepositoryBLL();

       }

       public List<Employee> SearchEmployee()

       {

          return this.repositoryEmployee.SearchEmployee();

          

       }

    }

   

    6:最後就是UI了。
   

pfx 轉換pem_EF_08

pfx 轉換pem_List_09

View Code 
static void Main(string[] args)

        {

            EmployeeRepositoryService ers = new EmployeeRepositoryService();

            var list = ers.SearchEmployee();

            var people = from p in list

                         orderby p.CreatedOn

                         select p;


            Console.WriteLine("All People:");

            foreach (var person in people)

            {

                Console.WriteLine("- {0}", person.ChineseName);

            }

            Console.WriteLine("Press any key to exit...");

            Console.ReadKey();

        }

     補充説明:

     1:添加完edmx後,以及完成添加代碼生成項後,查詢PersonModel.Context.cs,代碼如下:
    

public FacePerfEntities()

            : base("name=FacePerfEntities")

        {

        }

 

       構造函數中的參數FacePerfEntities,其實就對應EF數據庫連接串的節點名稱。

     2:添加完edmx後,在DAL層還會有一個packages.config文件,這個文件不用發佈到UI程序下面,也不影響程序運行,只需要將連接串對應的節點複製到UI配置文件中即可。

     總結: 經過上面的改造,已經越來越適合實際項目了,EF在不斷改進,我想在一些小型項目中快速開發倒是蠻適合的。