• (转)菜鸟级三层框架(EF+MVC)项目实战之 系列二 对数据访问层的抽象下


    原文地址:http://www.cnblogs.com/rdst/archive/2012/08/12/2635377.html

    概述:1、对数据访问层进行封装

             2、对业务层提供统一入口

             3、线程内实例唯一

    一、数据访问层封装抽象

        1.1、在程序集Cnblogs.Rdst.IDAO中创建IDBSession接口,其主要目的是将所有实体类封装为属性。

               

        1.2、IDBSession接口中定义SaveChange()方法,定义该方法的意义会在业务逻辑中介绍。

    复制代码
     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 partial interface IDBSession
     9     {
    10         int SaveChange();//用于在业务逻辑层对提交进行管理
    11     }
    12 }
    复制代码

         1.3、创建名为IDBSessionExt的T4模版,实现自动生成IDBSession的部分接口,其中将所有实体类定义为接口属性,以实现对数据访问层的封装。

    复制代码
    <#@ 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.IDAO
    {
      public partial interface IDbSession
      {
        <#foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
        {#>    
            I<#=entity.Name#>Dao <#=entity.Name#>Dao { get; set; }
        <#};#>
     }
    }
    复制代码

        1.4、T4模版编辑完成后,运行后生成的代码如下:

            

    二、数据访问层统一入口抽象

          在程序集Cnblogs.Rdst.IDAO中创建IDbSessionFactory接口,为业务逻辑层提供统一访问入口。

          该接口中定义GetCurrentDBSession()方法,其作用是通过该接口方法获取需要的实体对象。      

    复制代码
     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 IDBSessionFactory
     9     {
    10         IDBSession GetCurrentDBSession();
    11     }
    12 }
    复制代码

    三、实现IDBSession

       3.1、在Cnblogs.Rdst.Dao程序集中创建DBSession 部分类

              

       3.2、在Cnblogs.Rdst.Dao程序集中创建名为DBSessionExt的T4模版,将所有实体类自动封装为属性,以下是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.IDAO;
    
    namespace Cnblogs.Rdst.Dao
    {
      public partial class DBSession : IDBSession
      {
        <#foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
        {#>    
            private I<#=entity.Name#>Dao _<#=entity.Name#>Dao;
            public I<#=entity.Name#>Dao <#=entity.Name#>Dao
            {
                get
                {
                    if (_<#=entity.Name#>Dao == null)
                    {
                        _<#=entity.Name#>Dao = new <#=entity.Name#>Dao();
                    }
                    return _<#=entity.Name#>Dao;
                }
                set { _<#=entity.Name#>Dao = value; }
            }
        <#}#>
     }
    }
    复制代码

        3.3保存模版并运行,T4模版会自动将所有实体对象封装为属性。如下代码所示:

    复制代码
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using Cnblogs.Rdst.IDAO;
     6 
     7 namespace Cnblogs.Rdst.Dao
     8 {
     9   public partial class DBSession : IDBSession
    10   {
    11         
    12         private INoteInfoDao _NoteInfoDao;
    13         public INoteInfoDao NoteInfoDao
    14         {
    15             get
    16             {
    17                 if (_NoteInfoDao == null)
    18                 {
    19                     _NoteInfoDao = new NoteInfoDao();
    20                 }
    21                 return _NoteInfoDao;
    22             }
    23             set { _NoteInfoDao = value; }
    24         }
    25         
    26         private IUserInfoDao _UserInfoDao;
    27         public IUserInfoDao UserInfoDao
    28         {
    29             get
    30             {
    31                 if (_UserInfoDao == null)
    32                 {
    33                     _UserInfoDao = new UserInfoDao();
    34                 }
    35                 return _UserInfoDao;
    36             }
    37             set { _UserInfoDao = value; }
    38         }
    39      }
    40 }
    复制代码

         3.4、打开刚创建的DBSession类,实现IDBSession接口。并重新SaveChanges()方法,SaveChange()方法中调用了EF上下文中的SaveChange(),

                其用途会在业务逻辑层进行详细说明。

                以下是DBSession类中的实现代码:

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Cnblogs.Rdst.IDAO;
    using System.Data.Objects;
    
    namespace Cnblogs.Rdst.Dao
    {
        public partial class DBSession : IDBSession
        {
            private ObjectContext _efContext;
    
            //EF上下文
            public ObjectContext EfContext
            {
                get
                {
                    if (_efContext == null)
                    {
                      _efContext= ObjectContextFactory.GetCurrentObjectContext();
                    }
                    return _efContext;
                }
                set { _efContext = value; }
            }
    
            public int SaveChange()
            {
                return EfContext.SaveChanges();//调用SaveChanges()方法提交操作
            }
    
    
        }
    }
    复制代码

    四、实现数据访问层统一入口
          接下来现在我们需要在Cnblogs.Rdst.Dao程序集中实现IDbSessionFactory接口

          创建DBSessionFactory类并实现IDbSessionFactory接口,为了避免资源浪费,也用到了CallContex实现了线程内实例唯一。

          以下是DBsessionFactory类中的实现代码:

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Cnblogs.Rdst.IDAO;
    using System.Runtime.Remoting.Messaging;
    
    namespace Cnblogs.Rdst.Dao
    {
       public class DBSessionFactory:IDBSessionFactory
        {
            public IDBSession GetCurrentDBSession()
            {
                IDBSession dbSession = CallContext.GetData(typeof(DBSessionFactory).FullName) as DBSession;
                if (dbSession == null)
                { 
                   dbSession=new DBSession();
                   CallContext.SetData(typeof(DBSessionFactory).FullName, dbSession);
                }
                return dbSession;
            }
        }
    }
    复制代码


    至此,我们就已经完成了对数据访问层的封装。

    总结:1、方便了对数据库的替换数据库,只需要在ObjectContextFactory中进行替换相应的FE上下文。

             2、当数据库中的表或字段有更新时,我们只需要重新运行一下相应T4模版,就可以实现与数据库保存一致。

    接下来的系列三中会介绍业务逻辑层是如何调用数据访问层,稍后会进行更新。  

      

          

  • 相关阅读:
    gdb调试的基本使用
    重构改善代码--代码的坏味道
    17级单片机期中测试题目
    左右固定,中间自适应的三栏式布局五种写法
    存一些可能会用得到的vue的UI框架
    vue父子组件传值
    [Vue warn]: Missing required prop: "title"
    js中的值类型和引用类型的区别
    vue+node+mongoDB 火车票H5(四)---完成静态页面
    vue+node+mongoDB 火车票H5(三)---git提交时忽略不想提交的文件
  • 原文地址:https://www.cnblogs.com/fcsh820/p/2636576.html
Copyright © 2020-2023  润新知