zoukankan      html  css  js  c++  java
  • 对数据访问层的抽象中

    概要: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
     
    1.2 在Interface文件夹中添加名为Cnblogs.Rdst.IDAO的程序集
    1.2.1
     
    1.3 添加引用系列一中创建的Domain程序集和System.Data.Entity程序集
     
     
    1.3           
     
    二、抽象数据访问层的基接口
     
    2.1 在刚创建的Cnblogs.Rdst.IDAO程序集中创建IBaseDao接口
     
    2
    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

              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方法定义。

            3.3         

           3.4

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

     
     
  • 相关阅读:
    RabbitMQ一:消息队列的认识
    RabbitMQ二:AMQP协议
    SVN中如何去除版本控制器
    Asp.net:MVC认识
    时间连接查询展示
    C#string类型总结
    JavaScript01天学习笔记分享
    UML中的类图及类图之间的关系
    23 种设计模式的分类和功能
    WCF入门
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2635524.html
Copyright © 2011-2022 走看看