作为ERP等数据应用程序,数据库的处理是重中之重。

在框架中,我封装了一个数据库的基类,在每个模组启动或窗体启动过程中,实例化一个基类即可调用CRUD操作(create 添加read读取 update 修改delete删除),当然,还包括基础的SQL事务处理。

这个过程中,还考虑到对插件的管控,利用反射增加了调用授权,避免未经授权的程序盗用数据连接。

看看完整的代码:

    /// <summary>
    /// 数据库连接基类
    /// </summary>
    public class DBContext
    {
        /// <summary>
        /// 默认的加密方法Key,用于用户密码加密等次要场合
        /// </summary>
        private readonly string DftAESKeyOfDlls = "James Wang";
        /// <summary>
        /// 数据库连接字符串和用于外挂DLL或EXE的注册加密KEY,根据程序集的标题加密,写入到说明中,后面对2个值进行比对.
        /// </summary>
        private readonly string PlugRegKey = "*^*James/Wang/";
        //private string DftAESKeyOfDllsOfBase = "12345876543210";

        /// <summary>
        /// 本类内部明文连接串
        /// </summary>
        private readonly string ConnStr = null;

        /// <summary>
        /// 经测试后,数据库是否可正常连接
        /// </summary>
        public bool IsConnected = false;

        /// <summary>
        /// 连接出错后记录的错误信息
        /// </summary>
        public string ConnectErrorMessage = string.Empty;

        /// <summary>
        /// 加密后的数据库连接字符串,引用的地方要进行解密
        /// </summary>
        public string ConnStrShare = null;

        #region 数据连接的初始化
        /// <summary>
        /// 以全局信息的ConnStrCurAct连接串为依据初始化一个数据库连接.
        /// </summary>
        public DBContext()
        {
            //获取调用者的Title
            string tmpTitle = AssemblyInfos.GetAsbAttr(AssemblyInfos.AttrType.Title, Assembly.GetCallingAssembly());
            //获取调用者的说明
            string tmpDesc = AssemblyInfos.GetAsbAttr(AssemblyInfos.AttrType.Description, Assembly.GetCallingAssembly());
            if (tmpTitle != OCrypto.AES16Decrypt(tmpDesc, PlugRegKey))
            {
                MyMsg.Warning("调用者:"+tmpTitle+"未经过框架授权,无法引用数据连接.");
                return;
            }
            //没有指定连接则获取当前操作帐套的连接字符串;
            ConnStrShare = GlbInfo.ConnStrCurAct;
            ConnStr = OCrypto.AES16Decrypt(GlbInfo.ConnStrCurAct, PlugRegKey);
            Initial();
        }

        /// <summary>
        /// 以一个加密后的连接字串为依据初始化一个数据库连接.
        /// </summary>
        /// <param name="connStrEncrypted">已使用系统默认加密的连接字符串</param>
        public DBContext(string connStrEncrypted)
        {
            //获取调用者的Title
            string tmpTitle = AssemblyInfos.GetAsbAttr(AssemblyInfos.AttrType.Title, Assembly.GetCallingAssembly());
            //获取调用者的说明
            string tmpDesc = AssemblyInfos.GetAsbAttr(AssemblyInfos.AttrType.Description, Assembly.GetCallingAssembly());
            if (tmpTitle != OCrypto.AES16Decrypt(tmpDesc, PlugRegKey))
            {
                MyMsg.Warning("调用者:" + tmpTitle + "未经过框架授权,无法引用数据连接.");
                return;
            }
            ConnStrShare = connStrEncrypted;
            ConnStr = OCrypto.AES16Decrypt(connStrEncrypted, PlugRegKey);
            Initial();
        }
        private void Initial()
        {
            try
            {
                bool authorized = true;//这里取消了管制直接为True
                if (authorized)
                {
                    if (ConnStr == null)
                    {
                        throw (new Exception("连接字符串没有提供."));
                    }
                    else
                    {
                        IsConnected = TestConnection();
                    }
                }
                else
                {
                    return;
                }

            }
            catch (Exception ex)
            {
                MyMsg.Asterisk("未授权的操作!");
                throw ex;
            }
        }

        /// <summary>
        /// 测试数据库连接是否正常
        /// </summary>
        /// <returns></returns>
        private bool TestConnection()
        {
            try
            {
                ConnectErrorMessage = string.Empty;
                using (SqlConnection con = new SqlConnection(ConnStr))
                {
                    con.Open();
                    return true;
                }
            }
            catch (Exception ex)
            {
                ConnectErrorMessage = ex.Message;
                return false;
            }
        }
        #endregion

        #region SQL作业区域
        /// <summary>
        /// 执行UPDATE、INSERT 和 DELETE 语句,返回值为该命令所影响的行数。对于所有其他类型的语句,返回值为 -1。如果发生回滚,返回值也为 -1
        /// </summary>
        /// <param name="sqlText"></param>
        /// <param name="paras">参数列表,如new SqlParameter ("@Age",100)</param>
        public int RunSql(string sqlText, params SqlParameter[] paras)
        {
            try
            {
                using (SqlConnection con = new SqlConnection(ConnStr))
                {
                    con.Open();
                    using (SqlCommand cmd = new SqlCommand(sqlText, con))
                    {
                        cmd.Parameters.AddRange(paras);
                        int rst = cmd.ExecuteNonQuery();
                        cmd.Parameters.Clear(); //清除掉参数,如有OUTPUT则不能使用此句
                        return rst;
                    }
                }
            }
            catch (Exception ex)
            {
                MyMsg.Exclamation(ex.Message);
                throw ex;
            }
        }


        /// <summary>
        /// 批量执行SQL语句,传入SQL语句+参数的字典,如果是同样的语句重复执行,则使用"Lead"+i+"||||||"(6个|)的方法区分开每条语句避免传入失败.
        /// 各语句成功执行返回0,失败回滚返回-1
        /// </summary>
        /// <param name="dicSqls">SQL语句+参数字典</param>
        /// <param name="cmdTimeOut">CommandTimeout,此参数大于30时才起作用</param>
        /// <returns></returns>
        public int RunSqlsInTran(Dictionary<string, SqlParameter[]> dicSqls, int cmdTimeOut = 0)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(ConnStr))
                {
                    conn.Open();
                    using (SqlTransaction tran = conn.BeginTransaction()) //开始一个事务
                    {
                        using (SqlCommand cmd = conn.CreateCommand())
                        {
                            cmd.Transaction = tran;  //必须指定事务对象
                            //设置一个超时时间,需时过长的应该放在存储过程中处理
                            if (cmdTimeOut > 30) cmd.CommandTimeout = cmdTimeOut;  
                            //开始
                            if (dicSqls != null && dicSqls.Count >= 0)
                            {
                                foreach (KeyValuePair<string, SqlParameter[]> sqls in dicSqls)
                                {
                                    int m = sqls.Key.IndexOf("||||||");
                                    if (m >= 0)
                                    {
                                        cmd.CommandText = sqls.Key.Substring(m + 6);
                                    }
                                    else cmd.CommandText = sqls.Key;
                                    cmd.Parameters.Clear();
                                    if (sqls.Value != null) cmd.Parameters.AddRange(sqls.Value);
                                    cmd.ExecuteNonQuery();
                                }
                            }
                            //结束  
                            cmd.Parameters.Clear();  //清除掉参数,如有OUTPUT则不能使用此句
                        }
                        try
                        {
                            tran.Commit();//事务提交
                            return 0;
                        }
                        catch
                        {
                            tran.Rollback();//事务回滚
                            return -1;
                        }
                        finally
                        {
                        }
                    }//事务结束
                }
            }
            catch (Exception ex)
            {
                MyMsg.Exclamation(ex.Message);
                return -1;
            }
        }
        /// <summary>
        /// 按顺序批量执行SQL语句.
        /// 传入SQL语句+参数的字典,如果是同样的语句重复执行,则使用"Lead"+i+"||||||"的方法区分开每条语句避免传入失败.
        /// 成功执行后返回"{success:ok}"字符串,如果执行步骤出错,则返回步骤Lead字符串+"{error:..."的状态字,事务过程中出错返回"{exception-tran:..."
        /// 传入的所有语句都要有具有返回值(select要有记录,update等要有影响的行数),没有返回值则发生回滚。
        /// </summary>
        /// <param name="dicSqls"></param>
        /// <param name="cmdTimeOut">CommandTimeout,此参数大于30时才起作用</param>
        /// <returns></returns>
        public string RunSeqSqlsInTran(Dictionary<string, SqlParameter[]> dicSqls, int cmdTimeOut = 0)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(ConnStr))
                {
                    conn.Open();
                    string rtnValue = string.Empty;
                    using (SqlTransaction tran = conn.BeginTransaction()) //开始一个事务
                    {
                        using (SqlCommand cmd = conn.CreateCommand())
                        {
                            cmd.Transaction = tran;  //必须指定事务对象
                            if (cmdTimeOut > 30) cmd.CommandTimeout = cmdTimeOut;  //设置一个超时时间,需时过长的应该放在存储过程中处理
                            //开始
                            if (dicSqls != null && dicSqls.Count >= 0)
                            {
                                object tmpO = null;
                                int runRstRows = 0;
                                foreach (KeyValuePair<string, SqlParameter[]> sqls in dicSqls)
                                {
                                    int m = sqls.Key.IndexOf("||||||");
                                    if (m >= 0)
                                    {
                                        rtnValue = sqls.Key.Substring(0, m);
                                        cmd.CommandText = sqls.Key.Substring(m + 6);
                                    }
                                    else
                                    {
                                        rtnValue = "未指定的作业";
                                        cmd.CommandText = sqls.Key;
                                    }
                                    cmd.Parameters.Clear();
                                    if (sqls.Value != null) cmd.Parameters.AddRange(sqls.Value);
                                    if (cmd.CommandText.Trim().Substring(0, 6) == "SELECT")
                                    {
                                        tmpO = cmd.ExecuteScalar();
                                        if (tmpO == null)
                                        {
                                            tran.Rollback();//事务回滚
                                            return "{error:" + rtnValue + "}";
                                        }
                                    }
                                    else
                                    {
                                        runRstRows = cmd.ExecuteNonQuery();
                                        if (runRstRows <= 0)
                                        {
                                            tran.Rollback();//事务回滚
                                            return "{error:" + rtnValue + "}";
                                        }
                                    }
                                }
                            }
                            //结束
                            cmd.Parameters.Clear();  //清除掉参数,如有OUTPUT则不能使用此句
                        }
                        try
                        {
                            tran.Commit();//事务提交
                            return "{success:ok}";
                        }
                        catch (Exception ex)
                        {
                            tran.Rollback();//事务回滚
                            return "{exception-tran:" + ex.Message + "}";
                        }
                        finally
                        {
                        }
                    }//事务结束
                }
            }
            catch (Exception ex)
            {
                MyMsg.Exclamation(ex.Message);
                return "{exception:" + ex.Message + "}";
            }

        }
        /// <summary>
        /// 执行SQL语句,并填充指定的Dataset中的表(在填充之前会清空此表的原有数据,如有主从关联,则不能建立约束,或在执行前清除关联子表).
        /// </summary>
        /// <param name="tagDS">目标Dataset</param>
        /// <param name="tableName">目标表名</param>
        /// <param name="sqlText">SQL语句</param>
        /// <param name="paras">参数</param>
        /// <returns></returns>
        public bool SqlToDS(DataSet tagDS, string tableName, string sqlText, params SqlParameter[] paras)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(ConnStr))
                {
                    conn.Open();
                    using (SqlCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = sqlText;
                        cmd.Parameters.AddRange(paras);
                        SqlDataAdapter adapter = new SqlDataAdapter(cmd);
                        tagDS.Tables[tableName].Clear();    //先清除再填充,如有建立主从关联的会出错,可在调用端先处理清除.
                        adapter.Fill(tagDS, tableName);
                        cmd.Parameters.Clear();  //清除掉参数,如有OUTPUT则不能使用此句
                        return true;
                    }
                }
            }
            catch (Exception ex)
            {
                MyMsg.Information("提取数据到Dataset出错.", ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 执行SQL语句,并返回一个Datatable结果集
        /// </summary>
        /// <param name="sqlText"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public DataTable SqlToDT(string sqlText, params SqlParameter[] paras)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(ConnStr))
                {
                    conn.Open();
                    using (SqlCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = sqlText;
                        cmd.Parameters.AddRange(paras);
                        SqlDataAdapter adapter = new SqlDataAdapter(cmd);
                        DataSet dataset = new DataSet();
                        adapter.Fill(dataset);
                        cmd.Parameters.Clear();  //清除掉参数,如有OUTPUT则不能使用此句
                        return dataset.Tables[0];
                    }
                }
            }
            catch (Exception ex)
            {
                return null;
                throw ex;
            }
        }

        /// <summary>
        /// 执行SQL语句,并返回第一行第一列的值为string,如果记录不存在则返回空字符串, 执行出错则返回{error:XX}
        /// </summary>
        /// <param name="sqlText">sql语句</param>
        /// <param name="paras">参数</param>
        /// <returns></returns>
        public string SqlToString(string sqlText, params SqlParameter[] paras)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(ConnStr))
                {
                    conn.Open();
                    using (SqlCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = sqlText;
                        cmd.Parameters.AddRange(paras);
                        object rtnObj = cmd.ExecuteScalar();
                        cmd.Parameters.Clear();  //清除掉参数,如有OUTPUT则不能使用此句
                        if (rtnObj == null)
                        {
                            return string.Empty;
                        }
                        else return rtnObj.ToString();
                    }
                }
            }
            catch (Exception ex)
            {
                return "{error:" + ex.Message + "}";
            }
        }

        /// <summary>
        /// 从不同服务器插入大量数据到目标服务器的数据表中(使用了系统加密后的连接字符串)
        /// </summary>
        /// <param name="targetConnStr">加密后的目标服务器的连接字符串</param>
        /// <param name="targetDBTable">目标服务器中的目标表名称</param>
        /// <param name="sourceConnStr">加密后的数据获取来源服务器的连接字符串</param>
        /// <param name="sourceSqlText">获取数据的SQL语句</param>
        /// <param name="columnMap">表结构映射(可留空)</param>
        public bool BulkCopy(string targetConnStr, string targetDBTable, string sourceConnStr, string sourceSqlText, Dictionary<string, string> columnMap = null)
        {
            //还原连接字符串
            targetConnStr = OCrypto.AES16Decrypt(targetConnStr, DftAESKeyOfDlls);
            sourceConnStr = OCrypto.AES16Decrypt(sourceConnStr);
            //
            using (SqlConnection sourceConnection = new SqlConnection(sourceConnStr))
            {
                SqlCommand myCommand = new SqlCommand(sourceSqlText, sourceConnection);
                sourceConnection.Open();
                SqlDataReader reader = myCommand.ExecuteReader();
                // 目的
                using (SqlConnection targetConn = new SqlConnection(targetConnStr))
                {
                    // 打开连接
                    targetConn.Open();
                    using (SqlTransaction tran = targetConn.BeginTransaction()) //开始一个事务
                    {
                        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(targetConn))
                        {
                            if (columnMap != null && columnMap.Count >= 0)
                            {
                                foreach (KeyValuePair<string, string> pair in columnMap)
                                {
                                    bulkCopy.ColumnMappings.Add(pair.Key, pair.Value);
                                }
                            }
                            bulkCopy.BulkCopyTimeout = 0;
                            bulkCopy.BatchSize = 5000;
                            bulkCopy.NotifyAfter = 100000;
                            bulkCopy.DestinationTableName = targetDBTable;
                            bulkCopy.WriteToServer(reader);
                        }
                        try
                        {
                            tran.Commit();//事务提交
                            return true;
                        }
                        catch
                        {
                            tran.Rollback();//事务回滚
                            return false;
                        }
                        finally
                        {
                            reader.Close();
                        }

                    }
                }
            }
        }


        /// <summary>
        /// 从Datatable中插入大量数据到目标服务器的数据表中
        /// </summary>
        /// <param name="targetConnStr">目标服务器的连接字符串</param>
        /// <param name="targetDBTable">目标服务器中的目标表名称</param>
        /// <param name="sourceDT">原始数据Datatable</param>
        /// <param name="columnMap">表结构映射(可留空)</param>
        public bool BulkCopyDT(string targetConnStr, string targetDBTable, DataTable sourceDT, Dictionary<string, string> columnMap = null)
        {
            //还原连接字符串
            targetConnStr = OCrypto.AES16Decrypt(targetConnStr, DftAESKeyOfDlls);
            using (SqlConnection targetConn = new SqlConnection(targetConnStr))
            {
                // 打开连接
                targetConn.Open();
                using (SqlTransaction tran = targetConn.BeginTransaction()) //开始一个事务
                {
                    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(targetConn, SqlBulkCopyOptions.Default, tran))  //放入事务之中
                    {
                        if (columnMap != null && columnMap.Count >= 0)
                        {
                            foreach (KeyValuePair<string, string> pair in columnMap)
                            {
                                bulkCopy.ColumnMappings.Add(pair.Key, pair.Value);
                            }
                        }
                        bulkCopy.BulkCopyTimeout = 0;
                        bulkCopy.BatchSize = 800;
                        bulkCopy.NotifyAfter = 80000;
                        bulkCopy.DestinationTableName = targetDBTable;
                        bulkCopy.WriteToServer(sourceDT);
                    }
                    try
                    {
                        tran.Commit();//事务提交
                        return true;
                    }
                    catch
                    {
                        tran.Rollback();//事务回滚
                        return false;
                    }
                }
            }
        }

        /// <summary>
        /// 先插入到根据目标表创建的临时表,再做相关插入操作.如果目标表中有自增列,则表结构必须全部字段映射.如果先删除后插入,请注意使用的是TRUNCATE TABLE模式,数据不可恢复.
        /// </summary>
        /// <param name="targetConnStr">目标服务器的连接字符串</param>
        /// <param name="targetDBTable">目标服务器中的目标表名称</param>
        /// <param name="sourceConnStr">数据获取来源服务器的连接字符串</param>
        /// <param name="sourceSqlText">获取数据的SQL语句</param>
        /// <param name="keyField">主键字段名称(默认需提供),先删旧后插入新的情况下,可以留空.</param>
        /// <param name="DelBeforInsert">是否先删除旧数据,再新增新数据(默认为否)</param>
        /// <param name="columnMap">表结构映射(可留空)</param>
        /// <param name="hasAutoRKEY">如果有自增列,则表结构必须映射</param>
        /// <param name="needUpdateFlds">是否需要对旧数据执行更新操作,是的话则必须指定更新表达式</param>
        /// <param name="updFldsName">旧数据更新表达式,以逗号分隔.如:(YYPass,YYDept)表示将写入目标表中的YYPass,YYDept字段更新为来源数据.</param>
        public bool BulkCopyByTempTable(string targetConnStr, string targetDBTable, string sourceConnStr, string sourceSqlText, string keyField = "", bool DelBeforInsert = false, Dictionary<string, string> columnMap = null, bool hasAutoRKEY = false, bool needUpdateFlds = false, string updFldsName = "")
        {
            //还原连接字符串
            targetConnStr = OCrypto.AES16Decrypt(targetConnStr, DftAESKeyOfDlls);
            sourceConnStr = OCrypto.AES16Decrypt(sourceConnStr, DftAESKeyOfDlls);
            string columnsList = string.Empty;
            string whereStr = string.Empty;
            //
            using (SqlConnection sourceConnection = new SqlConnection(sourceConnStr))
            {
                SqlCommand myCommand = new SqlCommand(sourceSqlText, sourceConnection);
                sourceConnection.Open();
                SqlDataReader reader = myCommand.ExecuteReader();

                // 目的
                using (SqlConnection targetConn = new SqlConnection(targetConnStr))
                {
                    // 打开连接
                    targetConn.Open();

                    using (SqlTransaction tran = targetConn.BeginTransaction()) //开始一个事务
                    {
                        string tmpTabName = "atmpBCP" + DateTime.Now.Ticks.ToString();
                        using (SqlCommand cmd = new SqlCommand())
                        {
                            cmd.Connection = targetConn;
                            cmd.Transaction = tran;  //必须指定事务对象

                            cmd.CommandText = "SELECT * INTO " + tmpTabName + " FROM " + targetDBTable + " WHERE 1=2 "; //依照目标表创建临时表
                            cmd.ExecuteNonQuery();

                        }
                        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(targetConn, SqlBulkCopyOptions.Default, tran))  //放入事务之中
                        {
                            if (columnMap != null && columnMap.Count >= 0)
                            {

                                foreach (KeyValuePair<string, string> pair in columnMap)
                                {
                                    bulkCopy.ColumnMappings.Add(pair.Key, pair.Value);
                                    columnsList += pair.Value + ",";
                                }
                                columnsList = columnsList.Substring(0, columnsList.Length - 1);
                            }
                            bulkCopy.BulkCopyTimeout = 0;
                            bulkCopy.BatchSize = 800;
                            bulkCopy.NotifyAfter = 80000;
                            bulkCopy.DestinationTableName = tmpTabName;
                            bulkCopy.WriteToServer(reader);
                        }
                        //完成数据到临时表的插入后

                        using (SqlCommand dCommand = new SqlCommand())
                        {
                            dCommand.Connection = targetConn;
                            dCommand.Transaction = tran;  //必须指定事务对象

                            if (DelBeforInsert) //先删除再插入
                            {
                                dCommand.CommandText = "TRUNCATE TABLE " + targetDBTable;
                                dCommand.ExecuteNonQuery();

                                //插入新记录
                                if (hasAutoRKEY)
                                {
                                    dCommand.CommandText = "INSERT INTO " + targetDBTable + " (" + columnsList + ") SELECT " + columnsList + " FROM " + tmpTabName;
                                }
                                else
                                {
                                    dCommand.CommandText = "INSERT INTO " + targetDBTable + " SELECT * FROM " + tmpTabName;
                                }
                                dCommand.ExecuteNonQuery();

                            }
                            else //插入不存在的记录
                            {
                                //如果需要则更新旧数据,旧表和临时表结构一致
                                if (needUpdateFlds)
                                {
                                    if (!string.IsNullOrEmpty(updFldsName))
                                    {
                                        string updStr = string.Empty;
                                        string[] updFlds = OString.SplitStr(updFldsName, ",");//获取要更新的字段名
                                        foreach (string fldName in updFlds)
                                        {
                                            updStr += "[" + fldName + "]=" + tmpTabName + "." + "[" + fldName + "],";
                                        }
                                        updStr = OString.CutLastStrIf(updStr, ",");
                                        dCommand.CommandText = "UPDATE " + targetDBTable + " SET " + updStr + " FROM " + tmpTabName + " INNER JOIN " + targetDBTable + " ON " + tmpTabName + "." + keyField + " = " + targetDBTable + "." + keyField + "";
                                        dCommand.ExecuteNonQuery();
                                    }
                                }

                                //插入不存在的新记录
                                if (!string.IsNullOrEmpty(keyField))
                                {
                                    whereStr = " WHERE (" + keyField + " NOT IN (SELECT " + keyField + " FROM " + targetDBTable + "))";
                                }
                                if (hasAutoRKEY)
                                {
                                    dCommand.CommandText = "INSERT INTO " + targetDBTable + " (" + columnsList + ") SELECT " + columnsList + " FROM " + tmpTabName + whereStr;
                                }
                                else
                                {
                                    dCommand.CommandText = "INSERT INTO " + targetDBTable + " SELECT * FROM " + tmpTabName + whereStr;
                                }
                                dCommand.ExecuteNonQuery();
                            }

                        }

                        try
                        {
                            tran.Commit();//事务提交
                            return true;
                        }
                        catch
                        {
                            tran.Rollback();//事务回滚
                            return false;
                        }
                        finally
                        {
                            reader.Close();
                            //tran.Dispose();
                            using (SqlCommand dCmd = new SqlCommand())
                            {
                                dCmd.Connection = targetConn;
                                dCmd.CommandText = "DROP TABLE " + tmpTabName;  //操作完成删除临时表
                                dCmd.ExecuteNonQuery();
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 先清空目标表,再直接插入.
        /// </summary>
        /// <param name="targetConnStr">目标服务器的连接字符串</param>
        /// <param name="targetDBTable">目标服务器中的目标表名称</param>
        /// <param name="sourceConnStr">数据获取来源服务器的连接字符串</param>
        /// <param name="sourceSqlText">获取数据的SQL语句</param>
        /// <param name="columnMap">表结构映射(可留空)</param>
        public bool BulkCopyFirstClear(string targetConnStr, string targetDBTable, string sourceConnStr, string sourceSqlText, Dictionary<string, string> columnMap = null)
        {
            //还原连接字符串
            targetConnStr = OCrypto.AES16Decrypt(targetConnStr, DftAESKeyOfDlls);
            sourceConnStr = OCrypto.AES16Decrypt(sourceConnStr, DftAESKeyOfDlls);
            //
            using (SqlConnection sourceConnection = new SqlConnection(sourceConnStr))
            {
                SqlCommand myCommand = new SqlCommand(sourceSqlText, sourceConnection);
                sourceConnection.Open();
                SqlDataReader reader = myCommand.ExecuteReader();

                // 目的
                using (SqlConnection targetConn = new SqlConnection(targetConnStr))
                {
                    targetConn.Open();  // 打开连接

                    using (SqlTransaction tran = targetConn.BeginTransaction()) //开始一个事务
                    {
                        using (SqlCommand dCommand = new SqlCommand())
                        {
                            dCommand.Connection = targetConn;
                            dCommand.Transaction = tran;  //必须指定事务对象
                            dCommand.CommandText = "TRUNCATE TABLE " + targetDBTable;
                            dCommand.ExecuteNonQuery();
                        }

                        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(targetConn, SqlBulkCopyOptions.Default, tran))  //将批量作业加入事务之中
                        {
                            if (columnMap != null && columnMap.Count >= 0)
                            {
                                foreach (KeyValuePair<string, string> pair in columnMap)
                                {
                                    bulkCopy.ColumnMappings.Add(pair.Key, pair.Value);
                                }
                            }
                            bulkCopy.BulkCopyTimeout = 0;
                            bulkCopy.BatchSize = 800;
                            bulkCopy.NotifyAfter = 80000;
                            bulkCopy.DestinationTableName = targetDBTable;
                            bulkCopy.WriteToServer(reader);
                        }

                        try
                        {
                            tran.Commit();//事务提交
                            return true;
                        }
                        catch
                        {
                            tran.Rollback();//事务回滚
                            return false;
                        }
                        finally
                        {
                            reader.Close();
                        }

                    }

                }
            }
        }

        #endregion

        #region 存储过程PROCEDURE作业区域


        /// <summary>
        /// 执行存储过程,返回存储过程中return的int值
        /// </summary>
        /// <param name="procName">存储过程名称</param>
        /// <param name="paras">SqlParameter[]</param>
        /// <returns></returns>
        public int RunProcedure(string procName, params SqlParameter[] paras)
        {
            try
            {
                using (SqlConnection con = new SqlConnection(ConnStr))
                {
                    con.Open();
                    using (SqlCommand cmd = new SqlCommand(procName, con))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;

                        cmd.Parameters.AddRange(paras);

                        SqlParameter sp = cmd.Parameters.Add("procReturn", SqlDbType.Int);
                        sp.Direction = ParameterDirection.ReturnValue;
                        cmd.ExecuteNonQuery();
                        int pr = Convert.ToInt32(cmd.Parameters["procReturn"].Value);
                        return pr;
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>
        /// 执行存储过程,并返回字符串.
        /// </summary>
        /// <param name="procName">存储过程名称</param>
        /// <param name="inputOutputPra">输出参数名称,必须与存储过程中的参数定义相符</param>
        /// <param name="paras">参数</param>
        /// <returns></returns>
        public string ProcToString(string procName, string inputOutputPra, params SqlParameter[] paras)
        {
            try
            {
                using (SqlConnection con = new SqlConnection(ConnStr))
                {
                    con.Open();
                    using (SqlCommand cmd = new SqlCommand(procName, con))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;

                        cmd.Parameters.AddRange(paras);

                        SqlParameter sp = cmd.Parameters.Add(inputOutputPra, SqlDbType.NVarChar, 4000);
                        sp.Direction = ParameterDirection.InputOutput;
                        cmd.ExecuteNonQuery();
                        return cmd.Parameters[inputOutputPra].Value.ToString();
                    }
                }
            }
            catch (Exception ex)
            {
                return "{error:" + ex.Message + "}";
            }
        }

        /// <summary>
        /// 执行存储过程,并将第一行第一列作为返回字符串返回.
        /// </summary>
        /// <param name="procName">存储过程名称</param>
        /// <param name="paras">参数</param>
        /// <returns></returns>
        public string ProcSelToString(string procName, params SqlParameter[] paras)
        {
            try
            {
                using (SqlConnection con = new SqlConnection(ConnStr))
                {
                    con.Open();
                    using (SqlCommand cmd = new SqlCommand(procName, con))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;

                        cmd.Parameters.AddRange(paras);
                        return cmd.ExecuteScalar().ToString();
                    }
                }
            }
            catch (Exception ex)
            {
                return "{error:" + ex.Message + "}";
            }
        }
        /// <summary>
        /// 执行存储过程,并返回DataTable.
        /// </summary>
        /// <param name="procName">存储过程名称</param>
        /// <param name="paras">参数</param>
        /// <returns></returns>
        public DataTable ProcToDT(string procName, params SqlParameter[] paras)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(ConnStr))
                {
                    conn.Open();
                    using (SqlCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = procName;
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddRange(paras);
                        SqlDataAdapter adapter = new SqlDataAdapter(cmd);
                        DataSet dataset = new DataSet();
                        adapter.Fill(dataset);
                        cmd.Parameters.Clear();  //清除掉参数,如有OUTPUT则不能使用此句
                        return dataset.Tables[0];
                    }
                }
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// 判断记录是否存在
        /// </summary>
        /// <param name="fltSql">提供查找语句,如select A from Table1 where 1=1,必须返回一个字段</param>
        /// <returns></returns>
        public bool HasRecord(string fltSql)
        {
            string tmpRst = SqlToString(fltSql);
            if (!string.IsNullOrEmpty(tmpRst))
            {
                if (!(tmpRst.IndexOf("{error:") >= 0))
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 根据指定查找条件查找记录,没找到则执行新增语句,找到则执行更新语句.
        /// </summary>
        /// <param name="Sqlsearch">类似Select a from b where 1=1</param>
        /// <param name="sqlUpdate">更新语句</param>
        /// <param name="sqlInsert">新增语句</param>
        /// <returns></returns>
        public bool UpdateOrInsert(string Sqlsearch, string sqlUpdate, string sqlInsert)
        {
            int ret = 0;
            if (HasRecord(Sqlsearch))
            {
                ret = RunSql(sqlUpdate);
            }
            else
            {
                ret = RunSql(sqlInsert);
            }
            if (ret > 0) return true; else return false;
        }

        /// <summary>
        /// 按照指定的数据来源类型获取数据DT
        /// </summary>
        /// <param name="rcdSourceType">数据类型:SQLTEXT,VIEW,PROC,STRINGARRAY,错误类型将按SQLTEXT处理</param>
        /// <param name="rcdSource">数据来源</param>
        /// <param name="whereStr">查询字符串</param>
        /// <param name="paras">查询字符串中应用到的参数SqlParameter[]</param>
        /// <returns></returns>
        public DataTable GetDTBySourceType(string rcdSourceType, string rcdSource, string whereStr, SqlParameter[] paras)
        {
            rcdSourceType = rcdSourceType.ToUpper();
            DataTable dt = new DataTable();
            string sqlText = string.Empty;
            try
            {
                switch (rcdSourceType)
                {
                    case "SQLTEXT":  //SQL语句,一般应采用视图,性能比较高
                        sqlText = "SELECT * FROM (" + rcdSource + ") TmpA";
                        if (!string.IsNullOrEmpty(whereStr))
                        {
                            sqlText += " WHERE " + whereStr;
                        }
                        dt = SqlToDT(sqlText, paras);
                        break;
                    case "VIEW": //视图(用户输入的参数值用于视图查询)
                        sqlText = "SELECT * FROM " + rcdSource;
                        if (!string.IsNullOrEmpty(whereStr))
                        {
                            sqlText += " WHERE " + whereStr;
                        }
                        dt = SqlToDT(sqlText, paras);
                        break;
                    case "PROC": //存储过程只能接收参数,不能再附加WHERE条件
                        dt = ProcToDT(rcdSource, paras);
                        break;
                    case "STRINGARRAY": //字符串数组
                        dt = OString.StringToDT(rcdSource);
                        break;
                    default:
                        sqlText = "SELECT * FROM (" + rcdSource + ") TmpA";
                        if (!string.IsNullOrEmpty(whereStr))
                        {
                            sqlText += " WHERE " + whereStr;
                        }
                        dt = SqlToDT(sqlText, paras);

                        break;
                }
                return dt;
            }
            catch (Exception)
            {
                return null;
            }
        }
        #endregion


    }

DBContext.cs

其中最基础的一个方法:

/// <summary>
/// 执行UPDATE、INSERT 和 DELETE 语句,返回值为该命令所影响的行数。对于所有其他类型的语句,返回值为 -1。如果发生回滚,返回值也为 -1
/// </summary>

        public int RunSql(string sqlText, params SqlParameter[] paras)
        {
            try
            {
                using (SqlConnection con = new SqlConnection(ConnStr))    
                {
                    con.Open();
                    using (SqlCommand cmd = new SqlCommand(sqlText, con))
                    {
                        cmd.Parameters.AddRange(paras);
                        int rst = cmd.ExecuteNonQuery();
                        cmd.Parameters.Clear(); //清除掉参数,如有OUTPUT则不能使用此句
                        return rst;
                    }
                }
            }
            catch (Exception ex)
            {
                MyMsg.Exclamation(ex.Message);
                throw ex;
            }
        }

  前提是引用 :

using System.Data;
using System.Data.SqlClient;

  关于参数SqlParameter[]的传递:

SqlParameter[] paras = new SqlParameter[]
{
new SqlParameter(“@UserID”, postUserID),
new SqlParameter(“@PasswordHash”, postUserPass)
};

然后调用:

RunSql(“Select * from Users Where UserID=@UserID,PasswordHash=@PasswordHash”, paras);

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

大部分操作都可以通过这个类的方法来直接调用,我们需要的是编写优秀的SQL语句,那是一门更需要钻研的技能。

这个类的实例可以查看上一章登录窗体的代码。

 

版权声明:本文为imes原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/imes/p/9800350.html