首页 > 学院 > 开发设计 > 正文

C#通用数据库操作类

2019-11-14 13:31:39
字体:
来源:转载
供稿:网友

ADO.NET操作

使用ADO.NET的方式操作数据库时,对于经常需要操作不同数据库的同学,需要对不同的数据库翻来覆去地写操作类。


对ADO.NET,操作数据库需要有几个核心的东西(以MySQL为例):

MySqlConnection

负责mysql的连接,在操作mysql前,需要先获得连接。

MySqlCommand

负责具体命令的类,具体需要执行的sql的语句需要放到它的CommandText下。

MySqlDataAdapter

对于查询数据,可以选择使用DataAdapter将数据一次性取出到DataSet或者DataTable中。

MySqlDataReader

对于查询数据,同样可以使用Reader类对数据进行读取,与Adapter不同,Reader一次取得一条数据,可以在数据获取的过程中执行代码,而不需要等待数据一次性取出。

对于mysql有以上的几个主要类,对于SQLite、SQL Server,同样类似。
可以使用一个类来将他们包装,然后编译成dll,这样如果需要操作不同的数据库,只需要通过工厂创建不同的类即可。

提取相同点

使用ADO.NET方式的数据库驱动,他们都满足这么几个特点:

  • 上面列出的核心类都提供,而且都从对应的基类继承,例如MySqlConnection从SqlConnection继承。
  • Command类可以通过对应Connection的CreateCommand方法生成。

那么问题就简单了,我们只要操作他们的基类就可以了。然后他们的引用通过nuget获得,这样就能正常编译。

//主要代码    /// <summary>    /// 可以根据支持的Sql类型增加或删除类型,需要增加或删除对应的GetConnection和GetDbDataAdapter方法。    /// </summary>    public enum SqlType    {        SqlServer,        MySql,        PostgresQL,        Oracle,        SQLite,        //对ODBC方式需要格外注意,目标系统必须预先安装有对应的数据驱动,如果使用DSN,那么还需要使用配置ODBC数据源        Odbc    }    /// <summary>    /// 使用ADO.NET控制对数据库的基本访问方法,对同一个活动对象(不关闭)线程安全。    /// </summary>    public class SqlManipulation : IDisposable    {        public SqlManipulation(string strDSN, SqlType sqlType)        {            _sqlType = sqlType;            _strDSN = strDSN;        }        #region PRivate variables        private SqlType _sqlType;        private string _strDSN;        private DbConnection _conn;        private bool _disposed;        #endregion        private DbConnection GetConnection()        {            DbConnection conn;            switch (_sqlType)            {                case SqlType.SqlServer:                    conn = new SqlConnection(_strDSN);                    return conn;                case SqlType.MySql:                    conn = new MySqlConnection(_strDSN);                    return conn;                case SqlType.PostgresQL:                    conn = new NpgsqlConnection(_strDSN);                    return conn;                case SqlType.Oracle:                    conn = new OracleConnection(_strDSN);                    return conn;                case SqlType.SQLite:                    conn = new SQLiteConnection(_strDSN);                    return conn;                case SqlType.Odbc:                    conn = new OdbcConnection(_strDSN);                    return conn;                default:                    return null;            }        }        private DbDataAdapter GetDbDataAdapter(string sql)        {            DbDataAdapter adp;            switch (_sqlType)            {                case SqlType.SqlServer:                    adp = new SqlDataAdapter(sql, _conn as SqlConnection);                    return adp;                case SqlType.MySql:                    adp = new MySqlDataAdapter(sql, _conn as MySqlConnection);                    return adp;                case SqlType.PostgresQL:                    adp = new NpgsqlDataAdapter(sql, _conn as NpgsqlConnection);                    return adp;                case SqlType.Oracle:                    adp = new OracleDataAdapter(sql, _conn as OracleConnection);                    return adp;                case SqlType.SQLite:                    adp = new SQLiteDataAdapter(sql, _conn as SQLiteConnection);                    return adp;                case SqlType.Odbc:                    adp = new OdbcDataAdapter(sql, _conn as OdbcConnection);                    return adp;                default:                    return null;            }        }        private DbCommand GetCommand(DbConnection conn, string strSQL)        {            DbCommand command = conn.CreateCommand();            command.CommandText = strSQL;            return command;        }        /// <summary>        /// 初始化连接并打开        /// </summary>        /// <returns></returns>        public bool Init()        {            try            {                _conn = GetConnection();                _conn.Open();                return true;            }            catch (Exception e)            {                //记录日志,退出                MessageBox.Show(e.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);                return false;            }        }        /// <summary>        /// 执行SELECT查询语句,并返回DataTable对象。        /// </summary>        /// <param name="strSQL">需要执行的sql语句</param>        /// <returns>DataTable对象</returns>        public DataTable ExcuteQuery(string strSQL)        {            DbDataAdapter adp = GetDbDataAdapter(strSQL);            DataTable dt = new DataTable();            try            {                adp.Fill(dt);            }            catch (Exception e)            {                //记录日志,并返回空                MessageBox.Show(strSQL + "/n" + e.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);                return null;            }            return dt;        }        /// <summary>        /// 执行非Select语句,包括UPDATE DELETE INSERT        /// </summary>        /// <param name="strSQL">需要执行的sql语句</param>        /// <returns>受影响的行数</returns>        public int ExcuteNonQuery(string strSQL)        {            //实例化OdbcCommand对象            DbCommand myCmd = GetCommand(_conn, strSQL);            try            {                //执行方法                return myCmd.ExecuteNonQuery();            }            catch (Exception e)            {                //记录日志,并返回0                MessageBox.Show(strSQL + "/n" + e.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);                return 0;            }        }        /// <summary>        /// 通过事务批量执行非查询SQL语句        /// </summary>        /// <param name="strSQLs">需要批量执行的SQL</param>        /// <returns>受影响的行数,发生回滚则返回-1</returns>        public int ExecuteNonQueryTransaction(List<string> strSQLs)        {            DbCommand myCmd = GetCommand(_conn, "");            int sumAffected = 0;            DbTransaction transaction = _conn.BeginTransaction();            myCmd.Transaction = transaction;            try            {                foreach (var n in strSQLs)                {                    myCmd.CommandText = n;                    sumAffected += myCmd.ExecuteNonQuery();                }                transaction.Commit();                return sumAffected;            }            catch (Exception e)            {                MessageBox.Show(e.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);                transaction.Rollback();                return -1;            }        }    }
  • 由于不同数据库对数据类型的实现不同,不同数据库在操作command parameter上也有一些不同,所以暂时没有加入到此类中去。
  • 最开始,想使用反射来达到目的,可以避免switch分支,后来想起反射需要知道Assembly名称,写这段代码还不如直接switch。

完整项目代码github地址:https://github.com/circler3/DatabaseInvoke.git
(现在已经对mysql、sql server、posgresql、sqlite和ODBC方式支持)

未来的改进

  1. 考虑添加EF的支持(引用使用EF的程序,主程序app.config或者web.config需要添加配置项目)
  2. 代码重构
  3. 数据库现在是持续保持打开,拟增加其他选项

写在最后

程序比较简单,代码放在github上,欢迎交流。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表