zoukankan      html  css  js  c++  java
  • 菜鸟级三层框架(EF+MVC)项目实战之 系列三 业务逻辑层封装

    概述:业务逻辑层封装相对数据访问层来说较为简单,我们分为以下几步:

             1、抽象基接口定义CRUD方法

             2、应用T4模版生成所有实体接口

             3、接口实现

    一、接口定义

         1.1、创建名为Cnblogs.Rdst.IBLL的程序集,主要用于业务逻辑层接口定义

                 并引用Cnblogs.Rdst.Domain和System.Data.Entity。这里需要注意,只要是用到EF实体,就需要添加System.Data.Entity引用。

                

                

           1.2、创建IBaseService接口定义CRUD方法

                  这里可以直接将IBaseDao中定义的方法拷贝过来。

                

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 
     6 namespace Cnblogs.Rdst.IBLL
     7 {
     8     public interface IBaseService<T>
     9                        where T:class,
    10                        new ()
    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 }

          1.3、创建名为IServiceExt的T4模版,用于自动生成所有实体对象的接口,并继承自IBaseService接口
                 以下是T4模版中的代码:

    <#@ 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.Domain;
    
    namespace Cnblogs.Rdst.IBLL
    {
    <#
    foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
    {#>    
        public interface I<#=entity.Name#>Service : IBaseService<<#=entity.Name#>>
        {
        }
    <#};#>
    }

            

            以下是T4模版运行后,自动为我们生成的代码:


           

            至此,业务逻辑层的接口就定义完成了。

    二、抽象出业务逻辑层的基类

          2.1、创建名为Cnblogs.Rdst.BLL程序集,并添加DAO、Domain、IBLL、IDAO、System.Data.Entity程序集引用,如下图

                

        2.2、接下来是我们的重点,创建名为BaseService基类。该基类中实现了对数据访问层的调用,也实现了CRUD

               步骤: 1、先将IDBSessionFactory封装为属性,用于获取IDBSession

                         2、再将IDBSession封装为属性,用于获取EF上下文对象

                         3、定义IBaseDao类型的CurrentDao属性,用于属性获取具体的实体对象

                         4、定义抽象方法 SetCurrentDao(),用于子类设置实现,为CurrentDao属性赋具体的实体对象

              以下是这部分代码实现:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using Cnblogs.Rdst.IDAO;
     6 using Cnblogs.Rdst.Dao;
     7 
     8 
     9 namespace Cnblogs.Rdst.BLL
    10 {
    11     public abstract  class BaseService<T>
    12                     where T : class,
    13                     new()
    14     {
    15         //构造函数
    16         public BaseService()
    17         {
    18             //调用SetCurrentDao()方法,要求子类必须实现
    19             SetCurrentDao();
    20         }
    21 
    22         //获取EF实体工厂
    23         IDBSessionFactory _dbSessionFactory;
    24         IDBSession _dbSession;
    25 
    26         public IDBSessionFactory DbSessionFactory
    27         {
    28             get
    29             {
    30                 if (_dbSessionFactory == null)
    31                 {
    32                     _dbSessionFactory = new DBSessionFactory();
    33                 }
    34                 return _dbSessionFactory;
    35             }
    36             set { _dbSessionFactory = value; }
    37         }
    38 
    39 
    40         public IDBSession DbSession
    41         {
    42             get
    43             {
    44                 if (_dbSession == null)
    45                 {
    46                     _dbSession = DbSessionFactory.GetCurrentDBSession();//通过数据访问层提供的工厂获取EF实体对象
    47                 }
    48                 return _dbSession;
    49             }
    50             set { _dbSession = value; }
    51         }
    52         //数据访问层基接口类型可以接收数据访问层的所有实体Dao
    53         public IBaseDao<T> CurrentDao { get; set; }
    54 
    55         //该方法用于子类实现,其作用是设置相应的实体Dao
    56         public abstract void SetCurrentDao();
              //以下是CRUD实现
    

         2.3、实现CRUD
                有了EF上下文,我们就可以实现CRUD

                在实现增加和更新方法是,我们这时调用DBSessin中封装的SaveChanges()方法进行提交,主要目的是实现业务层控制提交。

                由于EF具有延迟加载特性,因此我们利用此特性,实现批量操作时,一次提交数据库,已提程序高性能。

                因此我们这时需要将BaseDao中的增加和更新方法中的SaveChange()方法注视掉,在此我就不贴出此部分代码了。

                以下是CRUD实现代码:

     1         //以下是CRUD实现
     2 
     3         public virtual IQueryable<T> LoadEntites(Func<T, bool> whereLambda)
     4         {
     5             return this.CurrentDao.LoadEntites(whereLambda);
     6         }
     7 
     8 
     9         public virtual IQueryable<T> LoadEntites(Func<T, bool> whereLambda, int pageIndex, int pageSize, out int totalCount)
    10         {
    11             return this.CurrentDao.LoadEntites(whereLambda, pageIndex, pageSize, out totalCount);
    12         }
    13 
    14 
    15         public virtual T AddEntity(T entity)
    16         {
    17             var tmp= this.CurrentDao.AddEntity(entity);
    18             this.DbSession.SaveChange();
    19             return tmp;
    20         }
    21 
    22 
    23         public virtual T UpdateEntity(T entity)
    24         {
    25             var tmp= this.CurrentDao.UpdateEntity(entity);
    26             this.DbSession.SaveChange();
    27             return tmp;
    28         }
    29 
    30 
    31         public virtual bool DelEntity(T entity)
    32         {
    33             return this.CurrentDao.DelEntity(entity);
    34         }
    35 
    36 
    37         public virtual bool DelEntityByWhere(Func<T, bool> whereLambda)
    38         {
    39             return this.DelEntityByWhere(whereLambda);
    40         }
    41     }
    42 }

          至此,BaseService业务逻辑层基类就封装完成,接下来使用T4模版自动生成所有实体。

          2.4、创建名为ServiceExt的T4模版

                 以下是模版中的代码:

    <#@ 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.IBLL;
    using Cnblogs.Rdst.Domain;
    
    namespace Cnblogs.Rdst.BLL
    {
    <#
    foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
    {#>    
        public partial class <#=entity.Name#>Service : BaseService<<#=entity.Name#>>, I<#=entity.Name#>Service
        {
           public override void SetCurrentDao()
           {
               this.CurrentDao = this.DbSession.<#=entity.Name#>Dao;
           }
        }
    <#};#>
    }

            以下是运行T4模版后自动生成的代码:

    这时我们就对业务逻辑层封装完成,系列四中使用MVC3.0简单实现增删改查以及分页功能。

           

  • 相关阅读:
    DHCP Option 60 的理解
    几种开源分词工具的比較
    推荐交互设计师阅读的一本书
    iOS IAP教程
    艰苦的RAW格式数据恢复之旅
    BestCoder Round #11 (Div. 2) 前三题题解
    罗马数字
    mysql 加入列,改动列,删除列。
    杂项:ASP.NET Web API
    杂项:Web API
  • 原文地址:https://www.cnblogs.com/rdst/p/2637210.html
Copyright © 2011-2022 走看看