zoukankan      html  css  js  c++  java
  • C# Winform下一个热插拔的MIS/MRP/ERP框架12(数据处理基类)

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

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

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

    看看完整的代码:

        /// <summary>
        /// 数据库连接基类
        /// </summary>
        public class DBContext
        {
            /// <summary>
            /// 本类内部明文连接串
            /// </summary>
            private string ConnStr = null;
    
            /// <summary>
            /// 经测试后,数据库是否可正常连接
            /// </summary>
            public bool IsConnected = false;
    
            /// <summary>
            /// 连接出错后记录的错误信息
            /// </summary>
            public string ConnectErrorMessage = string.Empty;
    
            /// <summary>
            /// 加密后的数据库连接字符串,引用的地方要进行解密.
            /// <para>在需要做Socket快速检测的情况下,连接串会包含TestRegion->FastCheckIP:192.168.0.1;FastCheckPort:1433;FastCheckTimeOut:2000;附串,解密后应该去除才能正常使用打开连接。</para>
            /// </summary>
            public string ConnStrShare = null;
    
            /// <summary>
            /// 当前DBContext使用的数据库名称
            /// </summary>
            public string DBName = string.Empty;
    
            #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, Core.MasterAESKey))
                {
                    MyMsg.Warning("调用者:" + tmpTitle + "未经过框架授权,无法引用数据连接.");
                    return;
                }
                //没有指定连接则获取当前操作帐套的连接字符串;
                ConnStrShare = GlbInfo.ConnStrCurAct;
                ConnStr = OCrypto.AES16Decrypt(GlbInfo.ConnStrCurAct, Core.MasterAESKey);
                Initial();
            }
    
            /// <summary>
            /// 以一个加密后的连接字串为依据初始化一个数据库连接.
            /// <para>在需要做Socket快速检测的情况下,连接串应包含TestRegion->FastCheckIP:192.168.0.1;FastCheckPort:1433;FastCheckTimeOut:2000;附串以便做Socket快速连接测试。</para>
            /// </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, Core.MasterAESKey))
                {
                    MyMsg.Warning("调用者:" + tmpTitle + "未经过框架授权,无法引用数据连接.");
                    return;
                }
                ConnStrShare = connStrEncrypted;
                ConnStr = OCrypto.AES16Decrypt(connStrEncrypted, Core.MasterAESKey);
                Initial();
            }
            private void Initial()
            {
                try
                {
                    //StackTrace trace = new StackTrace();
                    //MethodBase method = trace.GetFrame(1).GetMethod();
                    //MyMsg.Asterisk(method.Module.Name);
                    //Guid ownGUID = new Guid(((GuidAttribute)Attribute.GetCustomAttribute(Assembly.GetCallingAssembly(), typeof(GuidAttribute))).Value);
                    //MyMsg.Asterisk("GetCallingAssembly:"+ownGUID.ToString());
                    //Guid ownGUID1 = new Guid(((GuidAttribute)Attribute.GetCustomAttribute(Assembly.GetEntryAssembly(), typeof(GuidAttribute))).Value);
                    //MyMsg.Asterisk("GetEntryAssembly:" + ownGUID1.ToString());
                    //Guid ownGUID2 = new Guid(((GuidAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(GuidAttribute))).Value);
                    //MyMsg.Asterisk("GetExecutingAssembly:" + ownGUID2.ToString());
                    //Guid ownGUID3 = new Guid(((GuidAttribute)Attribute.GetCustomAttribute(Assembly.GetAssembly(method.Module.GetType()), typeof(GuidAttribute))).Value);
                    //MyMsg.Asterisk("GetAssembly(method.GetType()):"+ownGUID3.ToString());
    
                    //调用者在授权模块清单之中.ATCore.dll,AITO.exe,ATCust.exe,ATData.dll,ATProj.exe
                    //bool Authed = StrFunc.StrInArray(method.Module.Name, Crypt.AES16Decrypt(Properties.Settings.Default.CORE_SHARED_TO, AES_KEY));
                    bool authorized = 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;
                    if(ConnStr.IndexOf("FastCheckIP:")>=0 && ConnStr.IndexOf("FastCheckPort:") >= 0)
                    {
                        string fastChkIP = OString.GetMidStr(ConnStr, "FastCheckIP:", ";").Trim();
                        int fastCheckPort = OString.NZ2Int(OString.GetMidStr(ConnStr, "FastCheckPort:", ";").Trim());
                        int fastCheckTimeOut = OString.NZ2Int(OString.GetMidStr(ConnStr, "FastCheckTimeOut:", ";").Trim());
                        if (!string.IsNullOrEmpty(fastChkIP) && fastCheckPort>0 && fastCheckTimeOut>0)
                        {
                            string textRst = ONetwork.TestSokectConn(fastChkIP, fastCheckPort, fastCheckTimeOut);
                            if (textRst != "OK")
                            {
                                ConnectErrorMessage = textRst;
                                return false;
                            }
                        }
                    }
                    ConnStr = OString.LeftOf(ConnStr, "TestRegion->");
                    using (SqlConnection con = new SqlConnection(ConnStr))
                    {
                        con.Open();
                        DBName = con.Database;
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    ConnectErrorMessage = ex.Message;
                    return false;
                }
            }
            #endregion
    
            /// <summary>
            /// 用MasterAESKey还原已经加密过的字符串,并去除掉额外的用于Socket测试的属性
            /// </summary>
            /// <param name="connStrEncred"></param>
            /// <returns></returns>
            private string GetRConnStr(string connStrEncred)
            {
                return ConnStr = OString.LeftOf(OCrypto.AES16Decrypt(connStrEncred, Core.MasterAESKey), "TestRegion->");
            }
    
            #region SQL作业区域
            /// <summary>
            /// 执行UPDATE、INSERT 和 DELETE 语句,返回值为该命令所影响的行数。对于所有其他类型的语句,返回值为 -1。如果发生回滚,返回值也为 -1
            /// <para>尽量使用 “>=”,不要使用 ">"</para>
            /// <para>进行Insert、update的时候,应该防止冲突(特别是数据量大的时候,锁会升级)</para>
            /// <para>LIKE使用注意(尽量不采用 “%1%” 之类的方式处理,多采用 “1% ”、“%1”)</para>
            /// <para>避免连接字段查询(如 a.c1+'|'+b.c2 = XXXX,应该采用 a.c1= 'X' and b.c2 = 'XXX')</para>
            /// </summary>
            /// <param name="sqlText"></param>
            /// <param name="paras">参数列表,如new SqlParameter ("@Age",100)</param>
            public int RunSql(string sqlText, params SqlParameter[] paras)
            {
                try
                {
                    using (SqlConnection conn = new SqlConnection(ConnStr))
                    {
                        conn.Open();
                        if(conn.Database!=DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        using (SqlCommand cmd = new SqlCommand(sqlText, conn))
                        {
                            if (paras != null) 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();
                        if (conn.Database != DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        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();
                        if (conn.Database != DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        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:RunSeqSqlsInTran-" + rtnValue + "}";
                                            }
                                        }
                                        else
                                        {
                                            runRstRows = cmd.ExecuteNonQuery();
                                            if (runRstRows <= 0)
                                            {
                                                tran.Rollback();//事务回滚
                                                return "{error:RunSeqSqlsInTran-" + 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中的表(在填充之前会清空此表的原有数据,如有主从关联,则不能建立约束,或在执行前清除关联子表).
            /// <para>尽量使用 “>=”,不要使用 ">"</para>
            /// <para>进行Insert、update的时候,应该防止冲突(特别是数据量大的时候,锁会升级)</para>
            /// <para>LIKE使用注意(尽量不采用 “%1%” 之类的方式处理,多采用 “1% ”、“%1”)</para>
            /// <para>避免连接字段查询(如 a.c1+'|'+b.c2 = XXXX,应该采用 a.c1= 'X' and b.c2 = 'XXX')</para>
            /// </summary>
            /// <param name="tagDS">目标Dataset</param>
            /// <param name="tableName">目标表名,当为空时将填充Tables[0]</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();
                        if (conn.Database != DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        using (SqlCommand cmd = conn.CreateCommand())
                        {
                            cmd.CommandText = sqlText;
                            if (paras != null) cmd.Parameters.AddRange(paras);
                            SqlDataAdapter adapter = new SqlDataAdapter(cmd);
                            if (string.IsNullOrEmpty(tableName))
                            {
                                tagDS.Tables[0].Clear();    //先清除再填充,如有建立主从关联的会出错,可在调用端先处理清除.
                                adapter.Fill(tagDS.Tables[0]);
                            }
                            else
                            {
                                tagDS.Tables[tableName].Clear();
                                adapter.Fill(tagDS,tableName);
                            }
                            if(cmd.Parameters!=null) cmd.Parameters.Clear();  //清除掉参数,如有OUTPUT则不能使用此句
                            return true;
                        }
                    }
                }
                catch (Exception)
                {
                    return false;
                }
            }
    
            /// <summary>
            /// 执行SQL语句,并返回一个Datatable结果集
            /// <para>尽量使用 “>=”,不要使用 ">"</para>
            /// <para>进行Insert、update的时候,应该防止冲突(特别是数据量大的时候,锁会升级)</para>
            /// <para>LIKE使用注意(尽量不采用 “%1%” 之类的方式处理,多采用 “1% ”、“%1”)</para>
            /// <para>避免连接字段查询(如 a.c1+'|'+b.c2 = XXXX,应该采用 a.c1= 'X' and b.c2 = 'XXX')</para>
            /// </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();
                        if (conn.Database != DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        using (SqlCommand cmd = conn.CreateCommand())
                        {
                            cmd.CommandText = sqlText;
                            if (paras != null) 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)
                {
                    MyMsg.Exclamation(ex.Message);
                    return null;
                    throw ex;
                }
            }
    
            /// <summary>
            /// 执行SQL语句,并返回一个Datatable结果集的首行
            /// <para>尽量使用 “>=”,不要使用 ">"</para>
            /// <para>进行Insert、update的时候,应该防止冲突(特别是数据量大的时候,锁会升级)</para>
            /// <para>LIKE使用注意(尽量不采用 “%1%” 之类的方式处理,多采用 “1% ”、“%1”)</para>
            /// <para>避免连接字段查询(如 a.c1+'|'+b.c2 = XXXX,应该采用 a.c1= 'X' and b.c2 = 'XXX')</para>
            /// </summary>
            /// <param name="sqlText"></param>
            /// <param name="paras"></param>
            /// <returns></returns>
            public DataRow SqlToDRow(string sqlText, params SqlParameter[] paras)
            {
                try
                {
                    using (SqlConnection conn = new SqlConnection(ConnStr))
                    {
                        conn.Open();
                        if (conn.Database != DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        using (SqlCommand cmd = conn.CreateCommand())
                        {
                            cmd.CommandText = sqlText;
                            if (paras != null) cmd.Parameters.AddRange(paras);
                            SqlDataAdapter adapter = new SqlDataAdapter(cmd);
                            DataSet dataset = new DataSet();
                            adapter.Fill(dataset);
                            cmd.Parameters.Clear();  //清除掉参数,如有OUTPUT则不能使用此句
                            DataTable DTTmp = dataset.Tables[0];
                            if (DTTmp == null) return null;
                            if (DTTmp.Rows.Count < 1) return null;
                            return DTTmp.Rows[0];
                        }
                    }
                }
                catch (Exception ex)
                {
                    return null;
                    throw ex;
                }
            }
    
            /// <summary>
            /// 执行SQL语句,并返回第一行第一列的值为string,如果记录不存在则返回空字符串, 执行出错则返回{error:XX}
            /// <para>尽量使用 “>=”,不要使用 ">"</para>
            /// <para>进行Insert、update的时候,应该防止冲突(特别是数据量大的时候,锁会升级)</para>
            /// <para>LIKE使用注意(尽量不采用 “%1%” 之类的方式处理,多采用 “1% ”、“%1”)</para>
            /// <para>避免连接字段查询(如 a.c1+'|'+b.c2 = XXXX,应该采用 a.c1= 'X' and b.c2 = 'XXX')</para>
            /// </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();
                        if (conn.Database != DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        using (SqlCommand cmd = conn.CreateCommand())
                        {
                            cmd.CommandText = sqlText;
                            if (paras != null) 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:SqlToString-" + 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 = GetRConnStr(targetConnStr);
                sourceConnStr = GetRConnStr(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 = GetRConnStr(targetConnStr);
                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 = GetRConnStr(targetConnStr);
                sourceConnStr = GetRConnStr(sourceConnStr);
                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 = GetRConnStr(targetConnStr);
                sourceConnStr = GetRConnStr(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 (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 conn = new SqlConnection(ConnStr))
                    {
                        conn.Open();
                        if (conn.Database != DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        using (SqlCommand cmd = new SqlCommand(procName, conn))
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
    
                            if (paras != null) 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 conn = new SqlConnection(ConnStr))
                    {
                        conn.Open();
                        if (conn.Database != DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        using (SqlCommand cmd = new SqlCommand(procName, conn))
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
    
                            if (paras != null) cmd.Parameters.AddRange(paras);
    
                            SqlParameter sp = cmd.Parameters.Add(inputOutputPra, SqlDbType.NVarChar, 4000);
                            sp.Direction = ParameterDirection.InputOutput;
                            cmd.ExecuteNonQuery();
                            return OString.NZ2Str(cmd.Parameters[inputOutputPra].Value);
                        }
                    }
                }
                catch (Exception ex)
                {
                    return "{error:ProcToString-" + 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 conn = new SqlConnection(ConnStr))
                    {
                        conn.Open();
                        if (conn.Database != DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        using (SqlCommand cmd = new SqlCommand(procName, conn))
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
    
                            if (paras != null) cmd.Parameters.AddRange(paras);
                            return OString.NZ2Str(cmd.ExecuteScalar());
                        }
                    }
                }
                catch (Exception ex)
                {
                    return "{error:ProcSelToString-" + 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();
                        if (conn.Database != DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        using (SqlCommand cmd = conn.CreateCommand())
                        {
                            cmd.CommandText = procName;
                            cmd.CommandType = CommandType.StoredProcedure;
                            if (paras != null) 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>
            /// 判断记录是否存在(IF EXISTS (查找语句) SELECT 'OK' ELSE SELECT '')
            /// <para>当输入的语句错误时,也会返回False</para>
            /// </summary>
            /// <param name="fltSql">提供查找语句,如SELECT UserID FROM TB20U_User WHERE (UserID = 'uid'),必须返回一个字段</param>
            /// <returns></returns>
            public bool HasRecord(string fltSql)
            {
                fltSql = "IF EXISTS (" + fltSql + ") SELECT 'OK' ELSE SELECT ''";
                string tmpRst = SqlToString(fltSql);
                if (!string.IsNullOrEmpty(tmpRst))
                {
                    if (!(tmpRst.IndexOf("{error:") >= 0))
                    {
                        return true;
                    }
                    else
                    {
                        MyMsg.Warning("原始SQL语句执行异常,记录存在性判断可能会存在失误!请联系系统管理员处理。", tmpRst);
                        return false;
                    }
                }
                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>
            /// <param name="orderByStr">排序表达式(如:A DESC,B)</param>
            /// <returns></returns>
            public DataTable GetDTBySourceType(string rcdSourceType, string rcdSource, string whereStr, SqlParameter[] paras, string orderByStr = "")
            {
                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;
                            }
                            if (!string.IsNullOrEmpty(orderByStr))
                            {
                                sqlText += " ORDER BY " + orderByStr;
                            }
                            dt = SqlToDT(sqlText, paras);
                            break;
                        case "VIEW": //视图(用户输入的参数值用于视图查询)
                            sqlText = "SELECT * FROM " + rcdSource;
                            if (!string.IsNullOrEmpty(whereStr))
                            {
                                sqlText += " WHERE " + whereStr;
                            }
                            if (!string.IsNullOrEmpty(orderByStr))
                            {
                                sqlText += " ORDER BY " + orderByStr;
                            }
                            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;
                            }
                            if (!string.IsNullOrEmpty(orderByStr))
                            {
                                sqlText += " ORDER BY " + orderByStr;
                            }
                            dt = SqlToDT(sqlText, paras);
    
                            break;
                    }
                    return dt;
                }
                catch (Exception)
                {
                    return null;
                }
            }
            #endregion
    
    
        }
    DBContext.cs

    其中最基础的一个方法:

            public int RunSql(string sqlText, params SqlParameter[] paras)
            {
                try
                {
                    using (SqlConnection conn = new SqlConnection(ConnStr))
                    {
                        conn.Open();
                        if(conn.Database!=DBName) conn.ChangeDatabase(DBName);//避免架构变更后引起的对象名无效问题
                        using (SqlCommand cmd = new SqlCommand(sqlText, conn))
                        {
                            if (paras != null) 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语句,那是一门更需要钻研的技能。

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

  • 相关阅读:
    How To Build CyanogenMod Android for smartphone
    CentOS安装Code::Blocks
    How to Dual boot Multiple ROMs on Your Android SmartPhone (Upto Five Roms)?
    Audacious——Linux音乐播放器
    How to Dual Boot Multiple ROMs on Your Android Phone
    Everything You Need to Know About Rooting Your Android Phone
    How to Flash a ROM to Your Android Phone
    什么是NANDroid,如何加载NANDroid备份?
    Have you considered compiled a batman-adv.ko for android?
    BATMAN—Better Approach To Mobile Adhoc Networking (B.A.T.M.A.N.)
  • 原文地址:https://www.cnblogs.com/imes/p/9800350.html
Copyright © 2011-2022 走看看