惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Know Your Adversary
Know Your Adversary
小众软件
小众软件
L
LangChain Blog
月光博客
月光博客
博客园 - Franky
Microsoft Azure Blog
Microsoft Azure Blog
Y
Y Combinator Blog
有赞技术团队
有赞技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
MongoDB | Blog
MongoDB | Blog
Recorded Future
Recorded Future
V
Visual Studio Blog
TaoSecurity Blog
TaoSecurity Blog
S
Schneier on Security
C
Cybersecurity and Infrastructure Security Agency CISA
P
Privacy & Cybersecurity Law Blog
T
Threat Research - Cisco Blogs
D
DataBreaches.Net
L
LINUX DO - 热门话题
C
Check Point Blog
F
Fortinet All Blogs
Hugging Face - Blog
Hugging Face - Blog
The Hacker News
The Hacker News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Security Blog
Microsoft Security Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The GitHub Blog
The GitHub Blog
P
Proofpoint News Feed
L
Lohrmann on Cybersecurity
博客园 - 司徒正美
T
Threatpost
P
Palo Alto Networks Blog
A
About on SuperTechFans
Spread Privacy
Spread Privacy
Engineering at Meta
Engineering at Meta
N
News | PayPal Newsroom
T
Tailwind CSS Blog
The Last Watchdog
The Last Watchdog
Blog — PlanetScale
Blog — PlanetScale
A
Arctic Wolf
量子位
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 聂微东
Google Online Security Blog
Google Online Security Blog
Google DeepMind News
Google DeepMind News
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V
Vulnerabilities – Threatpost
H
Hacker News: Front Page

博客园 - 荣-

学习实践:使用模式,原则实现一个C++自动化测试程序 学习实践:使用模式,原则实现一个C++数据库访问类 C++字符转换等常用方法 DLL内存管理模板类 字符串处理代码(国际化转换C++版) 我的C++数据库访问库--临界区处理类 我的C++数据库访问库 批处理文件的学习 C++中,以类成员函数指针作为参数对std::map中的元素进行迭代处理 取得MySQL数据库表,列信息的SQL语句 ACE项目的重构整理 安装SQL Server 2000和sp补丁时,安装程序提示"以前的某个程序安装已在安装计算机上创建挂起的文件操作。运行安装程序之前必须重新启动计算机"。 我的计算机安装步骤 创建oracle用户 我的重构步骤 我的C++代码检查列表 PowerDesigner高级应用 文档的阅读 如何设计类
我的我的C#数据库操作类(与大家交流)
荣- · 2009-10-23 · via 博客园 - 荣-

1.   数据库操作类一览

我的数据库操作类一共有如下几种:

名称

描述

SqlDBOperate

SQL-Server数据库操作类

执行SQL-Server的数据库操作。

OracleDBOperate

Oracle数据库操作类

执行Oracle的数据库操作。

OleDBOperate

OleDb数据库操作类

通过OleDb执行数据库操作。

ODBCDBOperate

ODBC数据库操作类

通过ODBC执行数据库的操作。

2.   如何使用数据库操作类

SqlDBOperate oper = new SqlDBOperate(“…”);

String sql = “…”;

oper. ExecuteNonQuery(sql);

DataTable dt = oper.ExecuteDataTable(sql);

3.   数据库操作类的实现

各种数据库操作类的实现比较简单,SqlDBOperate,OracleDBOperate等类的代码不超过30行(当然更多代码放到了基类中),下面是具体操作类的代码:

SqlDBOperate

using System;

using System.Data.SqlClient;

using System.Data;

namespace DOTNET.Common.Database

{

    internal class SqlDBOperate : DBOperate

     {

         // 在构造方法中创建数据库连接

         public SqlDBOperate(string strConnection)

        {

            this.conn = new SqlConnection(strConnection);

        }

// 创建适配器

        protected override DbDataAdapter CreateDataAdapter(string sql)

        {

            return new SqlDataAdapter(sql, (SqlConnection)conn);

        }

     }

}

OracleDBOperate

using System;

using System.Data;

using System.Data.OracleClient;

namespace DOTNET.Common.Database

{

    public class OracleDBOperate : DBOperate

    {

        public OracleDBOperate(string strConnection)

        {

         // 在构造方法中创建数据库连接

            this.conn = new OracleConnection(strConnection);

        }

// 创建适配器

        protected override DbDataAdapter CreateDataAdapter(string sql)

        {

            return new OracleDataAdapter(sql, (OracleConnection)conn);

        }

    }

}

OleDBOperate

using System;

using System.Data.OleDb;

using System.Data;

namespace DOTNET.Common.Database

{

    internal class OleDBOperate : DBOperate

     {

         // 在构造方法中创建数据库连接

         public OleDBOperate(string strConnection)

         {

              this.conn = new OleDbConnection(strConnection);

         }

// 创建适配器

        protected override DbDataAdapter CreateDataAdapter(string sql)

        {

            return new OleDbDataAdapter(sql, (OleDbConnection)conn);

        }

     }

}

ODBCDBOperate

using System;

using System.Data.Odbc;

using System.Data;

namespace DOTNET.Common.Database

{

    internal class ODBCDBOperate : DBOperate

     {

         // 在构造方法中创建数据库连接

         public ODBCDBOperate(string strConnection)

         {

              this.conn = new OdbcConnection(strConnection);

         }

        // 创建适配器

        protected override DbDataAdapter CreateDataAdapter(string sql)

        {

            return new OdbcDataAdapter(sql, (OdbcConnection)conn);

        }

     }

}

其实,在这些数据库操作类中,所完成的仅仅只有在构造函数中创建数据库连接和提供合适的适配器方法而已,其它更多的方法在基类中提供。这样,当我们需要扩展一种新的数据库操作类型时,非常简单,只需要类似上面的10行代码而已。

那么基类都提供哪些功能呢?首先看基类是什么样子。

4.   数据库操作基类的实现

数据库操作基类有些大,有195行代码,程序行总数为385行,在代码后面我会讲解该类,其实该类不是很麻烦:

DBOperate

/// <copyright>天志(六子) 1999-2007</copyright>

/// <version>1.0</version>

/// <author>天志</author>

/// <email></email>

/// <log date="2007-04-05">创建</log>

using System;

using System.Data.SqlClient;

using System.Data.OleDb;

using System.Data;

using System.Data.Common;

namespace DOTNET.Common.Database

{

     /// <summary>

     /// 数据库操作抽象类。

     /// </summary>

     /// <author>天志</author>

     /// <log date="2007-04-05">创建</log>

     public abstract class DBOperate

    {

        /// <summary>

        /// 数据库连接对象。

        /// </summary>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        protected DbConnection conn;

        /// <summary>

        /// 事务处理对象。

        /// </summary>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        private DbTransaction trans;

        /// <summary>

        /// 指示当前操作是否在事务中。

        /// </summary>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        private bool bInTrans = false;

        #region 打开关闭数据库连接

        /// <summary>

        /// 打开数据库连接

        /// </summary>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        private void Open()

        {

            if (conn.State.Equals(ConnectionState.Closed))

            {

                conn.Open();

            }

        }

        /// <summary>

        /// 关闭数据库连接

        /// </summary>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        public void Close()

        {

            if (conn.State.Equals(ConnectionState.Open)) { conn.Close(); }

        }

        #endregion

        #region 事务支持

        /// <summary>

        /// 开始一个事务

        /// </summary>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        public void BeginTran()

        {

            if (!this.bInTrans)

            {

                this.Open();

                trans = conn.BeginTransaction();

                bInTrans = true;

            }

        }

        /// <summary>

        /// 提交一个事务

        /// </summary>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        public void CommitTran()

        {

            if (this.bInTrans)

            {

                trans.Commit();

                bInTrans = false;

                this.Close();

            }

        }

        /// <summary>

        /// 回滚一个事务

        /// </summary>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        public void RollBackTran()

        {

            if (this.bInTrans)

            {

                trans.Rollback();

                bInTrans = false;

                this.Close();

            }

        }

        #endregion

        #region 生成命令对象

        /// <summary>

        /// 获取一个DbCommand对象

        /// </summary>

        /// <param name="strSql">sql语句名称</param>

        /// <param name="parameters">参数数组</param>

        /// <param name="strCommandType">命令类型</param>

        /// <returns>OdbcCommand对象</returns>

        private DbCommand GetPreCommand(string sql, IDataParameter[] parameters)

        {

            // 初始化一个command对象

            DbCommand cmdSql = conn.CreateCommand();

            cmdSql.CommandText = sql;

            cmdSql.CommandType = this.GetCommandType(sql);

            // 判断是否在事务中

            if (this.bInTrans) { cmdSql.Transaction = this.trans; }

            if (parameters != null)

            {

                //指定各个参数的取值

                foreach (IDataParameter sqlParm in parameters)

                {

                    cmdSql.Parameters.Add(sqlParm);

                }

            }

            return cmdSql;

        }

        /// <summary>

        /// 取得SQL语句的命令类型。

        /// </summary>

        /// <param name="sql">SQL语句</param>

        /// <returns>命令类型</returns>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        private CommandType GetCommandType(string sql)

        {

            //记录SQL语句的开始字符

            string topText = "";

            if (sql.Length > 7)

            {

                //取出字符串的前位

                topText = sql.Substring(0, 7).ToUpper();

                // 如果不是存储过程

                if (topText.Equals("UPDATE ") || topText.Equals("INSERT ") ||

                    topText.Equals("DELETE ") || topText.Equals("ALTER T") ||

                    topText.Equals("ALTER ") || topText.Equals("BACKUP ") ||

                    topText.Equals("RESTORE") || topText.Equals("SELECT "))

                {

                    return CommandType.Text;

                }

            }

            return CommandType.StoredProcedure;

        }

        #endregion

        #region 执行无返回值SQL语句

        /// <summary>

        /// 执行添加,修改,删除之类的操作。

        /// </summary>

        /// <param name="strSql">sql语句名称</param>

        /// <param name="parameters">参数数组</param>

        /// <returns>受影响的条数</returns>

        public int ExecuteNonQuery(string sql, IDataParameter[] parameters)

        {

            DbCommand cmdSql = this.GetPreCommand(sql, parameters);

            try

            {

                // 打开数据库连接

                this.Open();

                return cmdSql.ExecuteNonQuery();

            }

            finally

            {

                // 如果不在事务中

                if (!this.bInTrans)

                {

                    this.Close();

                }

                cmdSql.Parameters.Clear();

            }

        }

        #endregion

        #region 返回单个值

        /// <summary>

        /// 返回结果集中第一行的第一列。

        /// </summary>

        /// <param name="sql">sql语句名称</param>

        /// <param name="parameters">参数数组</param>

        /// <returns>返回对象</returns>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        public object ExecuteScalar(string sql, IDataParameter[] parameters)

        {

            //初始化一个command对象

            DbCommand cmdSql = this.GetPreCommand(sql, parameters);

            try

            {

                //判断是否在事务中

                if (this.bInTrans)

                {

                    cmdSql.Transaction = this.trans;

                }

                // 打开数据库连接

                this.Open();

                return cmdSql.ExecuteScalar();

            }

            finally

            {

                //判断是否在事务中

                if (!this.bInTrans)

                {

                    this.Close();

                }

                cmdSql.Parameters.Clear();

            }

        }

        #endregion

        /// <summary>

        /// 返回DataReader。

        /// </summary>

        /// <param name="sql">sql语句名称</param>

        /// <param name="parameters">参数数组</param>

        /// <returns>DataReader对象</returns>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        public IDataReader ExecuteReader(string sql, IDataParameter[] parameters)

        {

            //初始化一个command对象

            DbCommand cmdSql = this.GetPreCommand(sql, parameters);

            try

            {

                // 打开数据库连接

                this.Open();

                //返回DataReader对象

                return cmdSql.ExecuteReader(CommandBehavior.CloseConnection);

            }

            finally

            {

                cmdSql.Parameters.Clear();

            }

        }

        #region 返回DataTable

        /// <summary>

        /// 返回DataTable。

        /// </summary>

        /// <param name="sql">sql语句名称</param>

        /// <param name="parameters">参数数组</param>

        /// <returns>DataTable对象</returns>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        public DataTable ExecuteDataTable(string sql, IDataParameter[] parameters)

        {

            //初始化一个DataAdapter对象,一个DataTable对象

            DataTable dt = new DataTable();

            DbDataAdapter da = this.CreateDataAdapter(sql);

            //初始化一个command对象

            DbCommand cmdSql = this.GetPreCommand(sql, parameters);

            try

            {

                //返回DataTable对象

                da.SelectCommand = cmdSql;

                // 打开数据库连接

                this.Open();

                da.Fill(dt);

                return dt;

            }

            finally

            {

                //判断是否在事务中

                if (!this.bInTrans)

                {

                    this.Close();

                }

                cmdSql.Parameters.Clear();

            }

        }

        #endregion

        #region 返回DataSet

        /// <summary>

        /// 返回DataSet对象。

        /// </summary>

        /// <param name="sql">sql语句名称</param>

        /// <param name="tableName">操作表的名称</param>

        /// <returns>DataSet对象</returns>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        public DataSet ExecuteDataSet(string sql, string tableName)

        {

            return this.ExecuteDataSet(sql, null, tableName);

        }

        /// <summary>

        /// 返回DataSet对象。

        /// </summary>

        /// <param name="sql">sql语句名称</param>

        /// <param name="parameters">参数数组</param>

        /// <param name="strTableName">操作表的名称</param>

        /// <returns>DataSet对象</returns>

        /// <author>天志</author>

        /// <log date="2007-04-05">创建</log>

        public DataSet ExecuteDataSet(string sql, IDataParameter[] parameters, string tableName)

        {

            //初始化一个DataSet对象,一个DataAdapter对象

            DataSet ds = new DataSet();

            DbDataAdapter da = this.CreateDataAdapter(sql);

            //初始化一个command对象

            DbCommand cmdSql = this.GetPreCommand(sql, parameters);

            try

            {

                // 返回DataSet对象

                da.SelectCommand = cmdSql;

                // 打开数据库连接

                this.Open();

                da.Fill(ds, tableName);

                return ds;

            }

            finally

            {

                //判断是否在事务中

                if (!this.bInTrans)

                {

                    this.Close();

                }

                cmdSql.Parameters.Clear();

            }

       }

        #endregion

        /// <summary>

        /// 创建适配器

        /// </summary>

        /// <param name="sql"></param>

        /// <returns></returns>

        protected abstract DbDataAdapter CreateDataAdapter(string sql);

     }

}

基类做了哪些事情呢?

该类的实现思路是:根据传入的SQL语句及SQL 参数数组,生成Command对象,然后执行Command对象,取得执行结果。

1.        首先是:判断传入的SQL参数是SQL语句还是存储过程。这个由方法GetCommandType实现:

如果以:INSERT ,SELECT ,UPDATE ,DELETE , ALTER ,ALTER T开头的sql参数,为SQL语句,否则即是存储过程。

2.        然后,根据SQL参数与SQL参数数组生成Command对象。这个由方法GetPreCommand实现:

1)        首先根据SQL参数取得Cpmmand的类型(CommandType.Text/CommandType.StoredProcedure.

2)        然后,循环SQL参数数组,将数组中的值赋值给Command对象。

3.         得到Command对象后,即可执行对Comamand的操作。这些方法有:

1)        ExecuteNonQuery:执行添加,修改,删除之类的操作。返回值为影响的记录数。

2)        ExecuteScalar:返回结果集中第一行的第一列。

3)        ExecuteReader:将数据库中的数据读到DataReader中。

4)        ExecuteDataSet:将数据库中的数据填充到DataSet中。

5)        ExecuteDataTable:将数据库中的数据填充到DataTable中。

4.         剩下的还有:对事务的支持:

1)        变量trans:类型为DbTransaction,事务对象。

2)        变量bInTransbool类型,是否启用事务。

3)        BeginTran方法:启动事务。

4)        CommitTran:提交事务。

5)        RollBackTran:事务回滚。

5.         添加事务后,对其他方法的影响:因为添加了事务,所以其他方法也受到影响:

1)        对GetPreCommand的影响:创建Command对象时,需要考虑是否需要设置Transaction。

2)        执行Comamand操作的影响:出现异常时,判断是否开启事务,如果未开启事务,则关闭连接(因为我假设的是如果不执行事务,则一次执行一条SQL语句:可以去掉本段处理本段处理时为了在无事务时,防止用户忘记关闭连接所添加的---我觉得这是段很鸡肋的代码)

6.         最后,还有常用的方法:打开/关闭数据库连接:

1)        connDbConnection类型,数据库连接对象。

2)        Open:打开数据库连接。

3)        Close:关闭数据库连接。

在本类中我们无法确定的是:

1)          数据库连接对象的真正类型:有派生类的构造函数负责创建。

2)            适配器(DbDataAdapter)的真正类型:提供抽象函数CreateDataAdapter有派生类负责实现。(CreateDataAdapter方法在ExecuteDataTableExecuteDataSet中被调用)

至此,我的数据库操作类介绍完成,这些类经过好几年,许多次的重构才成为现在这个样子,它可以用,但是还不完善,现在把它发布出来,希望能有感兴趣的同行,对它提出修改意见,共同完善它,也希望抛砖引玉。等有时间我把我的重构过程写出来与