菜鳥級三層框架(EF+MVC)項目實戰之 系列二 對數據訪問層的抽象中


概要:1、實現EF上線文線程唯一,有效避免了臟數據問題。

         2、實現IBaseDao中定義的CRUD方法

一、創建數據訪問層程序集

      1.1 在解決方案中創建Implements文件夾,以存放實現體部分的程序集          

          

      1.2 在Implements文件夾中創建Cnblogs.Rdst.Dao程序集

         

      1.3 添加如下引用

          

二、創建ObjectContextFactory獲取EF上下文

      2.1 在Cnblogs.Rdst.Dao程序集中創建ObjectContextFactory類,用來獲取EF上下文。

            當數據庫更換為Mysql或其他數據庫時,在這個類中可以實現替換。

            當網站訪問量增大時,為避免EF產生的臟數據問題,我們使用System.Runtime.Remoting.Messaging 命名空間下的CallContext來解決線程內上下文唯一。

            CallContex更多了解http://msdn.microsoft.com/zh-cn/library/system.runtime.remoting.messaging.callcontext(v=VS.80).aspx

     2.2  在ObjectContextFactory類中定義一個靜態方法,用於對EF上下文進行處理

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Data.Objects;
 4 using System.Linq;
 5 using System.Runtime.Remoting.Messaging;
 6 using System.Text;
 7 using Cnblogs.Rdst.Domain;
 8 using Cnblogs.Rdst.IDAO;
 9 
10 namespace Cnblogs.Rdst.Dao
11 {
12    public class ObjectContextFactory
13     {
14         public static System.Data.Objects.ObjectContext GetCurrentObjectContext()
15         {
16             //從CallContext數據槽中獲取EF上下文
17             ObjectContext objectContext = CallContext.GetData(typeof (ObjectContextFactory).FullName) as ObjectContext;
18             if (objectContext==null)
19             {
20                 //如果CallContext數據槽中沒有EF上下文,則創建EF上下文,並保存到CallContext數據槽中
21                 objectContext = new ModelContainer();//當數據庫替換為MySql等,只要在次出EF更換上下文即可。
22                 CallContext.SetData(typeof(ObjectContextFactory).FullName,objectContext);
23             }
24             return objectContext;
25         }
26     }
27 }

 

三、創建BaseDao,並實現CRUD方法

      3.1 創建BaseDao類,實現IBaseDao中定義方法,用於所有實體類繼承此基類。

           

     3.2 BaseDao類實現代碼

           EF應用中需要注意:1、增加和查詢是不需要附加實體的,如果刪除和更新不是從上下文獲取的實體,就需要先附加,再進行狀態更改。

                                     2、處理查詢,增刪改都需要調用SaveChange()提交操作。

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Data.Objects;
  4 using System.Linq;
  5 using System.Text;
  6 using Cnblogs.Rdst.IDAO;
  7 
  8 
  9 namespace Cnblogs.Rdst.Dao
 10 {
 11    public  class BaseDao<T>
 12                  where T:class,
 13                  new()
 14                     
 15    {
 16        ObjectContext objectContext= ObjectContextFactory.GetCurrentObjectContext() as ObjectContext;//獲取EF上下文
 17 
 18        /// <summary>
 19        /// 加載實體集合
 20        /// </summary>
 21        /// <param name="whereLambda"></param>
 22        /// <returns></returns>
 23        public virtual IQueryable<T> LoadEntites(Func<T,bool> whereLambda)
 24        {
 25           return objectContext.CreateObjectSet<T>().Where<T>(whereLambda).AsQueryable<T>();
 26        }
 27 
 28        /// <summary>
 29        /// 分頁加載數據
 30        /// </summary>
 31        /// <param name="whereLambda">過濾條件</param>
 32        /// <param name="pageIndex">頁碼</param>
 33        /// <param name="pageSize">頁大小</param>
 34        /// <param name="totalCount">總記錄數</param>
 35        /// <returns></returns>
 36        public virtual IQueryable<T> LoadEntites(Func<T,bool> whereLambda, int pageIndex, int pageSize, out int totalCount)
 37        {
 38           var tmp= objectContext.CreateObjectSet<T>().Where<T>(whereLambda);
 39           totalCount = tmp.Count();
 40 
 41           return tmp.Skip<T>(pageSize * (pageIndex - 1))//跳過行數,最終生成的sql語句是Top(n)
 42                     .Take<T>(pageSize) //返回指定數量的行
 43                     .AsQueryable<T>();
 44        }
 45 
 46        /// <summary>
 47        /// 添加實體
 48        /// </summary>
 49        /// <param name="entity"></param>
 50        /// <returns>返回更新后的實體</returns>
 51        public virtual T AddEntity(T entity)
 52        {
 53            objectContext.CreateObjectSet<T>().AddObject(entity);
 54            objectContext.SaveChanges();
 55            return entity;
 56        }
 57 
 58        /// <summary>
 59        /// 更新實體
 60        /// </summary>
 61        /// <param name="entity"></param>
 62        /// <returns>返回更新后的實體</returns>
 63        public virtual T UpdateEntity(T entity)
 64        {
 65            objectContext.CreateObjectSet<T>().Attach(entity);
 66            objectContext.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);//將附加的對象狀態更改為修改
 67            objectContext.SaveChanges();
 68            return entity;
 69        }
 70 
 71        /// <summary>
 72        /// 刪除實體
 73        /// </summary>
 74        /// <param name="entity"></param>
 75        /// <returns></returns>
 76        public virtual bool DelEntity(T entity)
 77        {
 78            objectContext.CreateObjectSet<T>().Attach(entity);
 79            objectContext.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Deleted);//將附加的實體狀態更改為刪除
 80            if (objectContext.SaveChanges()>0)
 81            {
 82                return true;//刪除成功
 83            }
 84            else
 85            {
 86                return false;//刪除失敗
 87            }
 88        }
 89 
 90        /// <summary>
 91        /// 根據條件刪除對象
 92        /// </summary>
 93        /// <param name="whereLambda">條件</param>
 94        /// <returns></returns>
 95        public virtual bool DelEntityByWhere(Func<T, bool> whereLambda)
 96        {
 97           var tmp= objectContext.CreateObjectSet<T>().Where<T>(whereLambda);//根據條件從數據庫中獲取對象集合
 98           foreach (var entity in tmp)
 99           {
100               objectContext.CreateObjectSet<T>().DeleteObject(entity);//標記對象為刪除狀態刪除
101           }
102           if (objectContext.SaveChanges() > 0) 
103           {
104               return true;
105           }
106           else
107           {
108               return false;
109           }
110        }
111    }
112 }

 

四、使用T4模版生成所有實體對象的實現

      4.1 和系列二中的方法一樣創建T4模版,生成所有的實體類繼承自BaseDao並實現各自的接口

           以下是T4模版中的代碼,需要更改相應的EF edmx模型路徑、引用命名空間等。

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#><#@
 output extension=".cs"#>
<#
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
CodeRegion region = new CodeRegion(this, 1);
MetadataTools ef = new MetadataTools(this);

string inputFile = @"..\\Cnblogs.Rdst.Domain\\Model.edmx";

EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
string namespaceName = code.VsNamespaceSuggestion();

EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
#>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cnblogs.Rdst.IDAO;
using Cnblogs.Rdst.Domain;

namespace Cnblogs.Rdst.Dao
{
<#
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{#>    
    public partial class <#=entity.Name#>Dao:BaseDao<<#=entity.Name#>>,I<#=entity.Name#>Dao
    {
      
    }
<#};#>
}

      4.2 T4模版編輯完成后,ctrl+s保存並運行,就生成了所有實體類的實現了

 

至此也就實現了數據訪問層的增刪改查以及分頁查詢。

菜鳥級三層框架(EF+MVC)項目實戰之 系列二 對數據訪問層的抽象下 將實現數據訪問層對業務層的統一入口


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM