zoukankan      html  css  js  c++  java
  • C#通用数据库操作类

    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 + "
    " + 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 + "
    " + 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上,欢迎交流。

  • 相关阅读:
    ppt中调整图片位置
    如何理解 Google Protocol Buffer
    g++: error: unrecognized command line option ‘-std=C++11’
    手把手教你如何加入到github的开源世界!
    redis
    maven
    Spring----注释----开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别
    JMX学习笔记(一)-MBean
    Redis学习笔记2-redis管道(pipeline)
    Redis学习笔记1-java 使用Redis(jedis)
  • 原文地址:https://www.cnblogs.com/podolski/p/5152537.html
Copyright © 2011-2022 走看看