登陆 注册
您的位置:
莫非网 -> 网络编程 -> NET教程 -> 编程内容

对数据访问层第一种实现(Acc+SQL)的重构

[ 作者:佚名  来源:不详  发布时间:2008-7-1 17:50:29    收藏此页到站长网摘]

昨天的文章基于.NET平台的分层架构实战(七)——数据访问层的第一种实现:Access+SQL发布后,很多朋友对我的程序提出了意见和建议,在这里先谢谢你们!!!尤其是 金色海洋(jyk),对我的程序提出了很多建设性的意见。

 我大体总结了一下,昨天程序的主要缺点有:
      1.Connection对象没有关闭
      2.DataReader对象没有关闭
      3.相似代码太多,造成代码冗余。

其中第一点问题,目前还没有太好的解决方案,主要是因为Connection一旦关闭,DataReader就无法读取了。而且,Connection对象应该会自动在适当的时候关闭(通过观察临时文件得出),并且在实际运行时并无影响(在功能上),所以这里没有专门解决。而针对后面两个问题,我使用了如下解决方案。

对于关闭DataReader的方法,实现起来很简单,在finally里将他关闭就行了。关键是如何去处冗余代码。

经过我的分析,数据访问层的操作可以分为三类:不返回数据,返回单个实体类,返回实体类集合。我将这三种操作的公共部分抽出,写成三个方法放在AccessDALHelper里,类型不同的问题使用泛型解决。

这样做有一个难题,就是不同实体在由DataReader转化为实体类时的代码很不一样,无法抽出。这里,我使用了Strategy模式解决。具体做法是:首先定义一个由DataReader转换为实体类的策略接口,然后为不同的实体编写不同的转换策略,示意图如下:

可以看出,所有转换策略都要实现IDataReaderToEntityStrategy接口,并且每个策略都有一个自组合,这是以为他们都要实现Singleton模式。而AccessDALHelper与具体策略无关,仅与接口耦合。

 

下面来看一下具体代码:

首先是IDataReaderToEntityStrategy接口


 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.Data;
 5using System.Data.OleDb;
 6
 7namespace NGuestBook.AccessDAL
 8{
 9    /// <summary>
10    /// 由DataReader转换成实体类的策略接口
11    /// </summary>

12    public interface IDataReaderToEntityStrategy<T>
13    {
14        /// <summary>
15        /// 将DataReader转换为实体类,采用泛型
16        /// </summary>
17        /// <param name="dataReader">包含数据的DataReader对象</param>
18        /// <returns>实体类</returns>

19        T DataReaderToEntity(OleDbDataReader dataReader);
20    }

21}

然后以Admin为例,看一下策略的具体实现:

1using System;
  2using System.Collections.Generic;
  3using System.Web;
  4using System.Web.Caching;
  5using System.Configuration;
  6using System.Data;
  7using System.Data.OleDb;
  8using NGuestBook.Utility;
  9
 10namespace NGuestBook.AccessDAL
 11{
 12    /// <summary>
 13    /// Access数据库操作助手
 14    /// </summary>

 15    public sealed class AccessDALHelper
 16    {
 17        /// <summary>
 18        /// 读取Access数据库的连接字符串
 19        /// 首先从缓存里读取,如果不存在则到配置文件中读取,并放入缓存
 20        /// </summary>
 21        /// <returns>Access数据库的连接字符串</returns>

 22        private static string GetConnectionString()
 23        {
 24            if (CacheAccess.GetFromCache("AccessConnectionString"!= null)
 25            {
 26                return CacheAccess.GetFromCache("AccessConnectionString").ToString();
 27            }

 28            else
 29            {
 30                string dbPath = ConfigurationManager.AppSettings["AccessPath"];
 31                string dbAbsolutePath = HttpContext.Current.Server.MapPath(dbPath);
 32                string connectionString = ConfigurationManager.AppSettings["AccessConnectionString"];
 33
 34                CacheDependency fileDependency = new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
 35                CacheAccess.SaveToCache("AccessConnectionString", connectionString.Replace("{DBPath}", dbAbsolutePath), fileDependency);
 36
 37                return connectionString.Replace("{DBPath}", dbAbsolutePath);
 38            }

 39        }

 40
 41        /// <summary>
 42        /// 执行SQL语句并且不返回任何值
 43        /// </summary>
 44        /// <param name="SQLCommand">所执行的SQL命令</param>
 45        /// <param name="parameters">参数集合</param>

 46        public static void ExecuteSQLNonQuery(string SQLCommand, OleDbParameter[] parameters)
 47        {
 48            OleDbConnection connection = new OleDbConnection(GetConnectionString());
 49            OleDbCommand command = new OleDbCommand(SQLCommand, connection);
 50
 51            for (int i = 0; i < parameters.Length; i++)
 52            {
 53                command.Parameters.Add(parameters[i]);
 54            }

 55
 56            connection.Open();
 57            command.ExecuteNonQuery();
 58            connection.Close();
 59        }

 60
 61        /// <summary>
 62        /// 执行SQL语句并返回包含查询结果的DataReader
 63        /// </summary>
 64        /// <param name="SQLCommand">所执行的SQL命令</param>
 65        /// <param name="parameters">参数集合</param>
 66        /// <returns></returns>

 67        public static OleDbDataReader ExecuteSQLDataReader(string SQLCommand, OleDbParameter[] parameters)
 68        {
 69            OleDbConnection connection = new OleDbConnection(GetConnectionString());
 70            OleDbCommand command = new OleDbCommand(SQLCommand, connection);
 71
 72            for (int i = 0; i < parameters.Length; i++)
 73            {
 74                command.Parameters.Add(parameters[i]);
 75            }

 76
 77            connection.Open();
 78            OleDbDataReader dataReader = command.ExecuteReader();
 79            //connection.Close();
 80
 81            return dataReader;
 82        }

 83
 84        /// <summary>
 85        /// 执行不需要返回数据的操作
 86        /// </summary>
 87        /// <param name="SQLCommand">SQL命令</param>
 88        /// <param name="parameters">参数</param>
 89        /// <returns>是否成功</returns>

 90        public static bool OperateNonData(string SQLCommand, OleDbParameter[] parameters)
 91        {
 92            try
 93            {
 94                ExecuteSQLNonQuery(SQLCommand, parameters);
 95                return true;
 96            }

 97            catch
 98            {
 99                return false;
100            }

101        }

102
103        /// <summary>
104        /// 执行返回单个实体类的操作
105        /// </summary>
106        /// <typeparam name="T">实体类类型</typeparam>
107        /// <param name="SQLCommand">SQL命令</param>
108        /// <param name="parameters">参数</param>
109        /// <param name="strategy">DataReader到实体类的转换策略</param>
110        /// <returns>实体类</returns>

111        public static T OperateEntity<T>(string SQLCommand, OleDbParameter[] parameters, IDataReaderToEntityStrategy<T> strategy)
112        {
113            OleDbDataReader dataReader = ExecuteSQLDataReader(SQLCommand, parameters);
114            try
115            {
116                if (!dataReader.HasRows)
117                {
118                    throw new Exception();
119                }

120
121                dataReader.Read();
122                return strategy.DataReaderToEntity(dataReader);
123            }

124            catch
125            {
126                return default(T);
127            }

128            finally
129            {
130                dataReader.Close();
131            }

132        }

133
134        /// <summary>
135        /// 执行返回实体类集合的操作
136        /// </summary>
137        /// <typeparam name="T">实体类类型</typeparam>
138        /// <param name="SQLCommand">SQL命令</param>
139        /// <param name="parameters">参数</param>
140        /// <param name="strategy">DataReader到实体类的转换策略</param>
141        /// <returns>实体类</returns>

142        public static IList<T> OperateEntityCollection<T>(string SQLCommand, OleDbParameter[] parameters, IDataReaderToEntityStrategy<T> strategy)
143        {
144            OleDbDataReader dataReader = AccessDALHelper.ExecuteSQLDataReader(SQLCommand, null);
145            try
146            {
147                if (!dataReader.HasRows)
148                {
149                    throw new Exception();
150                }

151
152                IList<T> entityCollection = new List<T>();
153                int i = 0;
154                while (dataReader.Read())
155                {
156                    entityCollection.Add(strategy.DataReaderToEntity(dataReader));
157                    i++;
158                }

159
160                return entityCollection;
161            }

162            catch
163            {
164                return default(IList<T