好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

对数据访问层的抽象中

对数据访问层的抽象中

概要: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)项目实战之 系列二 对数据访问层的抽象下 将实现数据访问层对业务层的统一入口

系列概述: 全系列会详细介绍抽象工厂三层的搭建,以及EF高级应用和 ASP.NET MVC3.0简单应用,应用到的技术有Ef、Lambda、Linq、Interface、T4等。

                 由于网上对涉及到的技术概念介绍很多,因此本项目中不再对基本概念加以叙述。  

 

系列二概述: 该系列详细介绍了如何抽象出公用方法(CRUD),以及T4模版的应用。


  一、创建Cnblogs.Rdst.IDAO程序集  

1.1 先在解决方案中创建一个Interface 文件夹,用于存放抽象出的接口

 

1.2 在Interface文件夹中添加名为Cnblogs.Rdst.IDAO的程序集

 

1.3 添加引用系列一中创建的Domain程序集和System.Data.Entity程序集

 

 

           

 

二、抽象数据访问层的基接口

 

2.1 在刚创建的Cnblogs.Rdst.IDAO程序集中创建IBaseDao接口

 

2.2 在IBaseDao中定义常用的CRUD方法

  1   using   System;
   2   using   System.Collections.Generic;
   3   using   System.Linq;
   4   using   System.Text;
   5  
  6   namespace   Cnblogs.Rdst.IDAO
   7   {
   8      public   interface  IBaseDao<T>
  9                    where  T: class  ,
  10                    new  () //  约束T类型必须可以实例化 
 11      {
  12          //  根据条件获取实体对象集合 
 13         IQueryable<T> LoadEntites(Func<T, bool >  whereLambda );
  14  
 15          //  根据条件获取实体对象集合分页 
 16         IQueryable<T> LoadEntites(Func<T, bool > whereLambda,  int  pageIndex,  int  pageSize, out   int   totalCount);
  17  
 18          //  增加 
 19          T AddEntity(T entity);
  20  
 21          //  更新 
 22          T UpdateEntity(T entity);
  23  
 24          //  删除 
 25          bool   DelEntity(T entity);
  26  
 27          //  根据条件删除 
 28          bool  DelEntityByWhere(Func<T,  bool >  whereLambda);
  29      }
  30  }

              此时基接口中的CRUD方法就定义完成。接下来我们需要使用T4模版生成所有的实体类接口并实现IBaseDao接口。

     三、生成所有的实体类接口

          3.1 添加名为IDaoExt 的T4文本模版

             

          3.2 在模版中贴入以下代码,其中注释的地方需要根据各自的项目进行更改

<#@ 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" ; //指定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.Domain; //引用Domain的命名空间 

 namespace  Cnblogs.Rdst.IDAO  //实体类接口所在的命名空间 
{
<#
 foreach  (EntityType entity  in  ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))  //便利edmx模型中映射的实体对象 
{#>    
     public   interface  I<#=entity.Name#>Dao:IBaseDao<<#=entity.Name#>>  //生成实体对象接口 
    {
    }
<#};#>
}

        3.3 T4模版编辑完成后,Ctrl+s保存,提示是否运行,点击确认。此时就自动帮我们生成了所有的实体类接口,并实现了IBaseDao接口,相应的也具有了CRUD方法定义。

                  

       

       菜鸟级三层框架(EF+MVC)项目实战之 系列二 对数据访问层的抽象中 会介绍实现类中是如何实现基接口中定义的方法

 

 

标签:  EF ,  Entity ,  框架 ,  接口 ,  抽象工厂

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于对数据访问层的抽象中的详细内容...

  阅读:38次