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

概述: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模版,就可以实现与数据库保存一致。

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

 

 

   

 

 

       

 

 

 

 

        

posted @ 2012-08-12 22:28  rdst  阅读(8231)  评论(5编辑  收藏  举报