我的数据访问类(第二版)—— for .net2.0 (一)

asp.net2.0已经出来好久了,由于许多的原因一直没有使用,一个月前才开始使用VS2005写东西。

这一个月里又重新学习了一下基础知识,比如多态、接口了什么的。

既然已经到了2.0了嘛,那么以前的数据访问的方式要不要变一下呢?简单看了一下,感觉还是我的那种方式好,至少时我已经用习惯了。那么用.net2.0的方法重写一遍吧。

看了一下Framework 2.0的代码,发现一个问题。虽然表面上ADO.NET的使用没有什么变化(加了一些功能,原来由的功能没有变),但是内部实现有比较大的变化,原来的接口的“工作”都改成了抽象基类。

正好可以利用这个特性来改一下支持多数据库的部分。

数据访问类分成了两个DLL,共 3+3个部分。

本着把变化提出来的思想,我把变化的地方编译成一个DLL,相对不变的地方编译成另一个DLL。

变化的地方又分为三个部分:读取web.config里的信息,基类,写错误日志。

不变的地方分为三个部分:SQL语句部分(静态函数),存储过程部分(需要实例化),填充实体类部分。

下面是容易变化的DLL代码:

读取Webconfig文件
using System;
using System.Web.Configuration;

namespace JYK.DataAccessLibrary
{
    public class WebConfig
    {

        public static readonly string ConnectionString = System.Web.Configuration.WebConfigurationManager.AppSettings["ConnString"];

        #region 读取webconfig里的连接字符串并返回
        /// <summary>
        /// 返回连接字符串
        /// </summary>
        /// <returns></returns>
        //public static string ConnectionString()
        //{
        //    return System.Web.Configuration.WebConfigurationManager.AppSettings["ConnString"];
        //}
        #endregion

        #region 读取webconfig里的数据库类型的信息并返回
        /// <summary>
        /// 返回数据库类型
        /// 1:SQL 2000 SQL2005
        /// 2:Orcale
        /// 3:OleDb
        /// 4:ODBC
        /// </summary>
        /// <returns></returns>
        public static int DataBaseType()
        {
            string show = System.Web.Configuration.WebConfigurationManager.AppSettings["DataBaseType"];
            if (show == null)
                return ;
            else
               return Int32.Parse(show);
             
        }
        #endregion

        #region 读取webconfig里的是否显示出错信息并返回
        /// <summary>
        /// 返回是否显示出错的SQL语句
        /// </summary>
        /// <returns></returns>
        public static bool isShowErrorSQL()
        {
            string show = System.Web.Configuration.WebConfigurationManager.AppSettings["isShowErrorSQL"];
            if (show == null)
            {
                return false;
            }
            else
            {
                if (show == "")
                    return false;
                else
                    return true;
            }

        }
        #endregion

    }
}

着里的处理并不是太好,只是还没有想到更好的方法。

主要是读取连接字符串和数据库类型。

==================================================

简单工厂,根据数据库类型返回实例对应的实例。

sing System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using JYK;

namespace JYK.DataAccessLibrary
{
    /// <summary>
    /// 返回Connection、Command、DataAdapter
    /// </summary>
    public class Factory
    {

        public static string DataBaseType = WebConfig.DataBaseType();
        #region Connection
        /// <summary>
        /// 根据webconfig返回一个Connection的实例。
        /// </summary>
        /// <returns></returns>
        public static DbConnection CreateConnection()
        {
            return CreateConnection(DataBaseType);
        }

        /// <summary>
        /// 返回一个Connection的实例
        /// </summary>
        /// <returns></returns>
        public static DbConnection CreateConnection(int DataBaseType)
        {
            switch (DataBaseType)
            {
                default:
                    return new System.Data.SqlClient.SqlConnection(WebConfig.ConnectionString);
               // case 2:
               //     return new ;
                case :
                    return new System.Data.OleDb.OleDbConnection(WebConfig.ConnectionString);
                case :
                    return new System.Data.Odbc.OdbcConnection(WebConfig.ConnectionString);
            }

        }
        #endregion

        #region Command
        public static DbCommand CreateCommand()
        {
            return CreateCommand(DataBaseType, "");
        }

        public static DbCommand CreateCommand(int DataBaseType)
        {
            return CreateCommand(DataBaseType, "");
        }

        public static DbCommand CreateCommand(string sql)
        {
            return CreateCommand(DataBaseType, sql);
        }

        /// <summary>
        /// 返回Command实例,并且设置Connection和CommandText
        /// </summary>
        /// <param name="DataBaseType"></param>
        /// <param name="sql"></param>
        /// <returns></returns>
        public static DbCommand CreateCommand(int DataBaseType, string sql)
        {
            DbCommand cm = null;
            cm = new System.Data.SqlClient.SqlCommand(sql, (System.Data.SqlClient.SqlConnection)CreateConnection());
            return cm;
        }
        #endregion

        #region DataAdapter
        public static DbDataAdapter CreateDataAdapter()
        {
            return CreateDataAdapter(DataBaseType, "");
        }

        public static DbDataAdapter CreateDataAdapter(string sql)
        {
            return CreateDataAdapter(DataBaseType, sql);
        }

        public static DbDataAdapter CreateDataAdapter(int DataBaseType)
        {
            return CreateDataAdapter(DataBaseType, "");
        }

        /// <summary>
        /// 返回DataAdapter的实例,并且设置SelectCommand和CommandText
        /// </summary>
        /// <param name="DataBaseType">数据库类型</param>
        /// <param name="sql">SQL语句</param>
        /// <returns></returns>
        public static DbDataAdapter CreateDataAdapter(int DataBaseType,string sql)
        {
            DbDataAdapter da = null;
            da = new System.Data.SqlClient.SqlDataAdapter();
            da.SelectCommand = CreateCommand(DataBaseType,sql);
            return da;
        }

        public static void DbDataAdapterDispose(DbDataAdapter da)
        {
            da.SelectCommand.Connection.Close();
            da.SelectCommand.Connection.Dispose();
            da.SelectCommand.Dispose();
            da.Dispose();
        }
        #endregion
      
    }
}

一、利用了System.Data.Common; 里面的一些基类。

System.Data.Common.DbProviderFactory 还没有研究,好像可以利用它来实现,去掉switch。

但是我觉得数据访问的地方是比较特殊的,

1、数据库的种类是有限的,常用的也就三个(对于.net来说):MS SQL 、Orcale 、Access(属于OleDb),算上不常用的应该超不过十种,全都算上也超不过30种吧。

2、变化慢,出现一种新的数据库要多长时间呢?好长好长吧。

3、运行效率高,访问数据库是很频繁的事情,应该尽量提高运行效率,去掉不必要的地方。

综上所述,我感觉switch更好一点。两外为什么说这里是容易变化的地方呢?因为这里可以做很多的变化。

a、比如说我只用MS SQL,不可能用到其它的数据库,那么我可以把 简化 CreateConnection() 函数,去掉判断的部分,直接返回 SqlConnection()。这样可以提高一点效率。

b、比如我只在MS SQL和 Orcale 之间切换,那么我可以只写两个判断,呵呵,以后再加数据库,再加一条判断就可以了。因为数据库的变换是很慢的,所以改动程序也没有什么麻烦的。

二、这里的处理也不是太好,至少缩小了使用范围,这么写的目的主要是让调用的地方减少点代码。两外也是按照我的习惯来写的。

======================================

记录出错信息的代码

using System;
using System.Collections.Generic;
using System.Text;

namespace JYK.DataAccessLibrary
{
    public class WriteLog
    {
        #region 设置出错信息
        /// <summary>
        /// 当发生异常时,所作的处理
        /// </summary>
        /// <param name="FunctionName">函数名称</param>
        /// <param name="commandText">查询语句或者存储过程</param>
        /// <param name="message">错误信息</param>
        public static string SetErrorMsg(string FunctionName, string commandText, string message)
        {
            //设置返回到上一层的错误信息
            string errorMsg = FunctionName + "函数出现错误。<BR>错误信息:" + message;
            if (WebConfig.isShowErrorSQL())
            {
                errorMsg += "<BR>查询语句:" + commandText;
                addLogErr(commandText, errorMsg);    //记录到错误日志
            }
            else
            {
                addLogErr(commandText, errorMsg + "<BR>查询语句:" + commandText);    //记录到错误日志
            }
            return errorMsg;

        }
        #endregion

        #region 记录错误日志
        //如果要使用的话,根据你的需要进行修改。
        public static void addLogErr(string SPName, string ErrDescribe)
        {
            //记录到错误日志
            string FilePath = System.Web.HttpContext.Current.Server.MapPath("/log/" + DateTime.Now.ToString("yyyyMMdd") + ".txt");
            System.Text.StringBuilder str = new System.Text.StringBuilder();
            str.Append(DateTime.Now.ToString());
            str.Append("\t");
            str.Append(SPName);
            str.Append("\t");
            str.Append(ErrDescribe.Replace("<BR>", ""));
            str.Append("\r\n");

            System.IO.StreamWriter sw = null;
            try
            {
                sw = new System.IO.StreamWriter(FilePath, true, System.Text.Encoding.Unicode);
                sw.Write(str.ToString());
            }
            catch (Exception ex)
            {
                System.Web.HttpContext.Current.Response.Write("没有访问日志文件的权限!或日志文件只读!<BR>" + ex.Message);
            }
            finally
            {
                if (sw != null)
                    sw.Close();
            }
        }
        #endregion
    }
}

这个对于经常在程序里面使用SQL语句的兄弟们是很实用的,因为它会把出错的SQL语句、出错的描述(ex.Message)、函数名称、出错的时间,写到一个文本文件里面。对于查错是很方便的。存储过程的话帮助不是很大,因为存储过程的出错描述总是让人很晕,记录下来帮助也不是很大。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏pangguoming

C# 事件(Event)

事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些出现,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。事件是用...

3765
来自专栏.NET技术

.net平台的MongoDB使用

  最近花了点时间玩了下MongoDB.Driver,进行封装了工具库,平常也会经常用到MongoDB,因此写一篇文章梳理知识同时把自己的成果分享给大家。

1382
来自专栏程序员的SOD蜜

打造轻量级的实体类数据容器

    这里有三个关键词:轻量级,实体类,数据容器,还有一个潜在的关键词:通用。这几个名词之间有什么联系呢?     一般来说,操作实体类往往伴随着一个实体类集...

22410
来自专栏林德熙的博客

C# 代码占用的空间

是不是代码会占用空间,如果一个程序初始化需要 100M 的代码,那么在他初始化之后,这些代码就没有作用了,他会不会占空间?本文经过测试发现,代码也是会占空间。

511
来自专栏小灰灰

Java 动手写爬虫: 二、 深度爬取

第二篇 前面实现了一个最基础的爬取单网页的爬虫,这一篇则着手解决深度爬取的问题 简单来讲,就是爬了一个网页之后,继续爬这个网页中的链接 1. 需求背景 背景...

72710
来自专栏NetCore

[原创]Fluent NHibernate之旅(四)-- 关系(中)

接着上一篇,我们继续讲解ORM中的关系。在数据库设计中,我们最多打交道的,要算一对多关系了,延续我们的示例,我们来讲解一下一对多的关系。 Fluent NHib...

21310
来自专栏MasiMaro 的技术博文

ATL模板库中的OLEDB与ADO

上次将OLEDB的所有内容基本上都说完了,从之前的示例上来看OLEDB中有许多变量的定义,什么结果集对象、session对象、命令对象,还有各种缓冲等等,总体上...

1432
来自专栏逸鹏说道

C#进阶系列——WebApi 接口参数不再困惑:传参详解上

前言:还记得刚使用WebApi那会儿,被它的传参机制折腾了好久,查阅了半天资料。如今,使用WebApi也有段时间了,今天就记录下API接口传参的一些方式方法,算...

4918
来自专栏hbbliyong

依赖注入(IOC)二

上一章我们讲了构造注入与设值注入,这一篇我们主要讲接口注入与特性注入。 接口注入 接口注入是将抽象类型的入口以方法定义在一个接口中,如果客户类型需要获得这个...

3537
来自专栏丑胖侠

Zookeeper客户端API之创建节点(七)

本篇博客主要讲一下使用Zookeeper原生的客户API来创建一个数据节点。 创建数据节点方法 Zookeeper提供了两个创建数据节点的方法。 同步创建数据节...

2429

扫码关注云+社区

领取腾讯云代金券