• 数据库C#操作类(支持所有MSSQL语法的数据库)


    这个是我经过几天做出来的,原创的是我的好伙伴【埖ó髒 QQ:3624091】,我在他的基础上做了改进,增加了分页处理方法并改进了Insert,Update,Delete三种方法的操作形式,做到了更精简,更方便,这里我给出这个方法,并演示我的集中关键的调用类里面的形式,给大家借鉴参考

    c# 代码
     
    1. /******************************************************  
    2.  * 项目模块:  
    3.  * 功能描述:数据库执行控制类  
    4.  * 创建者:埖ó髒  
    5.  * 创建日期:2007/9/22  
    6.  * 修改者:陈峰  
    7.  * 修改日期:2007/9/25  
    8.  * ***************************************************/  
    9. using System;   
    10. using System.Collections.Generic;   
    11. using System.Text;   
    12. using System.Data;   
    13. using System.ComponentModel;   
    14. using System.Collections;   
    15. using System.Data.SqlClient;   
    16.   
    17. namespace NMJU.Web.DataSQLServer   
    18. {   
    19.     /// <summary>   
    20.     /// 数据库执行控制类   
    21.     /// </summary>   
    22.     public class CmdFactory   
    23.     {   
    24.         static SqlConnection cn = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["MSSQLConnectionString"]);   
    25.   
    26.         public CmdFactory()   
    27.         {   
    28.   
    29.         }  
    30.  
    31.         #region 数据库执行操作   
    32.   
    33.         /* 执行更新删除插入数据库操作,成功则返回true */  
    34.         /// <summary>   
    35.         /// 功能:执行更新删除插入数据库操作,成功则返回true   
    36.         /// </summary>   
    37.         /// <param name="strSql"></param>   
    38.         /// <returns></returns>   
    39.         public static bool ExecuteScalar(string strSql)   
    40.         {   
    41.             bool flag = false;   
    42.             cn.Open();   
    43.             //操作   
    44.             SqlCommand cm = new SqlCommand();   
    45.             cm.CommandText = strSql;   
    46.             try  
    47.             {   
    48.                 cm.Connection = cn;   
    49.                 cm.ExecuteNonQuery();   
    50.             }   
    51.             catch (Exception ex)   
    52.             {   
    53.                 throw new Exception(ex.Message);   
    54.   
    55.             }   
    56.             finally  
    57.             {   
    58.                 cn.Close();   
    59.                 flag = true;   
    60.             }   
    61.             return flag;   
    62.   
    63.         }   
    64.         /* 执行查询数据库操作是否有记录 */  
    65.         /// <summary>   
    66.         /// 功能:执行查询数据库操作是否有记录    
    67.         /// </summary>   
    68.         /// <param name="strSql"></param>   
    69.         public static bool ExecuteScalarRead(string strSql)   
    70.         {   
    71.             cn.Open();   
    72.             SqlCommand cm = new SqlCommand();   
    73.             cm.CommandText = strSql;   
    74.             cm.Connection = cn;   
    75.             try  
    76.             {   
    77.                 SqlDataReader dr = cm.ExecuteReader();   
    78.                 if (dr.Read())   
    79.                 {   
    80.                     return true;   
    81.                 }   
    82.                 else  
    83.                 {   
    84.                     return false;   
    85.                 }   
    86.             }   
    87.             catch (Exception ex)   
    88.             {   
    89.                 throw new Exception(ex.Message);   
    90.             }   
    91.             finally  
    92.             {   
    93.                 cm.Dispose();   
    94.                 cn.Close();   
    95.             }   
    96.   
    97.         }   
    98.         /* 执行查询数据库操作返回多少条记录 */  
    99.         /// <summary>   
    100.         /// 功能:执行查询数据库操作返回多少条记录    
    101.         /// </summary>   
    102.         /// <param name="strSql"></param>   
    103.         public static int ExecuteScalarScalarCount(string strSql)   
    104.         {   
    105.             cn.Open();   
    106.             SqlCommand cm = new SqlCommand();   
    107.             cm.CommandText = strSql;   
    108.             cm.Connection = cn;   
    109.             try  
    110.             {   
    111.                 int count = (int)cm.ExecuteScalar();   
    112.                 return count;   
    113.             }   
    114.             catch (Exception ex)   
    115.             {   
    116.                 throw new Exception(ex.Message);   
    117.             }   
    118.             finally  
    119.             {   
    120.                 cm.Dispose();   
    121.                 cn.Close();   
    122.             }   
    123.   
    124.         }   
    125.         /* 执行查询数据库操作返回影响行数 */  
    126.         /// <summary>   
    127.         /// 功能:执行查询数据库操作返回影响行数    
    128.         /// </summary>   
    129.         /// <param name="strSql"></param>   
    130.         public static int ExecuteNonQueryCount(string strSql)   
    131.         {   
    132.             cn.Open();   
    133.             SqlCommand cm = new SqlCommand();   
    134.             cm.CommandText = strSql;   
    135.             cm.Connection = cn;   
    136.             try  
    137.             {   
    138.                 int count = (int)cm.ExecuteNonQuery();   
    139.                 return count;   
    140.             }   
    141.             catch (Exception ex)   
    142.             {   
    143.                 throw new Exception(ex.Message);   
    144.             }   
    145.             finally  
    146.             {   
    147.                 cm.Dispose();   
    148.                 cn.Close();   
    149.             }   
    150.   
    151.         }   
    152.         /*执行查询操作*/  
    153.         /// <summary>   
    154.         /// 功能:执行查询操作   
    155.         /// </summary>   
    156.         /// <param name="strSql"></param>   
    157.         /// <param name="ds">返回数据集</param>   
    158.         /// <returns></returns>   
    159.         public static DataSet ExecuteSelectCmmond(string strSQL, DataSet ds)   
    160.         {   
    161.             cn.Open();   
    162.             SqlCommand cm = new SqlCommand();   
    163.             cm.CommandText = strSQL;   
    164.             cm.Connection = cn;   
    165.             SqlDataAdapter da = new SqlDataAdapter(cm);   
    166.             try  
    167.             {   
    168.                 da.Fill(ds);   
    169.                 return ds;   
    170.             }   
    171.             catch (Exception ex)   
    172.             {   
    173.                 throw new Exception(ex.Message);   
    174.             }   
    175.             finally  
    176.             {   
    177.                 cm.Dispose();   
    178.                 cn.Close();   
    179.             }   
    180.         }   
    181.         public static DataSet ExecuteSelectCmmond(string strSQL)   
    182.         {   
    183.             cn.Open();   
    184.             SqlCommand cm = new SqlCommand();   
    185.             cm.CommandText = strSQL;   
    186.             cm.Connection = cn;   
    187.             SqlDataAdapter da = new SqlDataAdapter(cm);   
    188.             DataSet ds = new DataSet();   
    189.             try  
    190.             {   
    191.                 da.Fill(ds);   
    192.                 return ds;   
    193.             }   
    194.             catch (Exception ex)   
    195.             {   
    196.                 throw new Exception(ex.Message);   
    197.             }   
    198.             finally  
    199.             {   
    200.                 cm.Dispose();   
    201.                 cn.Close();   
    202.             }   
    203.         }   
    204.         /* 查询表结构操作*/  
    205.         /// <summary>   
    206.         ///功能: 查询表结构操作   
    207.         /// </summary>   
    208.         /// <param name="strSql"></param>   
    209.         /// <param name="ds">返回数据集</param>   
    210.         /// <returns></returns>   
    211.         public static DataSet GetTableCol(string TableName)   
    212.         {   
    213.             cn.Open();   
    214.             string strSql = "select * from [" + TableName + "] where 1> 2 ";   
    215.             SqlCommand cm = new SqlCommand();   
    216.             cm.CommandText = strSql;   
    217.             cm.Connection = cn;   
    218.             DataSet ds = new DataSet();   
    219.   
    220.             SqlDataAdapter da = new SqlDataAdapter(cm);   
    221.             try  
    222.             {   
    223.                 da.Fill(ds);   
    224.                 return ds;   
    225.             }   
    226.             catch (Exception ex)   
    227.             {   
    228.                 throw new Exception(ex.Message);   
    229.             }   
    230.             finally  
    231.             {   
    232.                 cn.Close();   
    233.             }   
    234.         }  
    235.  
    236.  
    237.         #endregion  
    238.  
    239.         #region 数据库应用操作   
    240.   
    241.         /* 绑定列表*/  
    242.         /// <summary>   
    243.         /// 绑定列表   
    244.         /// </summary>   
    245.         /// <param name="TableName">表名</param>   
    246.         /// <param name="WhereStr">条件,若条件为空,则不执行该参数</param>   
    247.         /// <param name="OrderStr">排序,若条件为空,则不执行该参数</param>   
    248.         /// <returns></returns>   
    249.         public static DataSet BuildSelectTable(string TableName, string WhereStr, string OrderStr)   
    250.         {   
    251.             string strSQL = "";   
    252.             DataSet ds = new DataSet();   
    253.             strSQL = "select * from [" + TableName + "] ";   
    254.             if (WhereStr != String.Empty)   
    255.             {   
    256.                 strSQL += " where " + WhereStr;   
    257.             }   
    258.             if (OrderStr != String.Empty)   
    259.             {   
    260.                 strSQL += " order by " + OrderStr;   
    261.             }   
    262.             // ExecuteClass ec = new ExecuteClass();   
    263.             ExecuteSelectCmmond(strSQL, ds);   
    264.             ds.Tables[0].TableName = TableName;   
    265.             return ds;   
    266.         }   
    267.         public static DataSet BuildSelectTable(string TableName)   
    268.         {   
    269.             string strSQL = "";   
    270.             DataSet ds = new DataSet();   
    271.             strSQL = "select * from [" + TableName + "]";   
    272.             // ExecuteClass ec = new ExecuteClass();   
    273.             ExecuteSelectCmmond(strSQL, ds);   
    274.             ds.Tables[0].TableName = TableName;   
    275.             return ds;   
    276.         }   
    277.   
    278.         /*进行insert,update,delete三纵操作*/  
    279.         /// <summary>   
    280.         /// 功能:进行insert,update,delete三纵操作   
    281.         /// </summary>   
    282.         /// <param name="htValues">字段数据的一个Hashtable</param>   
    283.         /// <param name="WhereStr">条件语句</param>   
    284.         /// <param name="TableName">表名</param>   
    285.         /// <param name="operators">执行操作的标识:insert,update,delete</param>   
    286.         /// <returns></returns>   
    287.         public static bool BuildSQLExecute(Hashtable htValues, string WhereStr, string TableName, string Operate)   
    288.         {   
    289.             //构架SQL语句   
    290.             string strSQL = "";   
    291.             string strCol = "";   
    292.   
    293.   
    294.             if (Operate.ToLower() == "insert")   
    295.             {   
    296.                 int j = 1;   
    297.                 foreach (DictionaryEntry de in htValues) //更新的字段列   
    298.                 {   
    299.   
    300.                     if (j < htValues.Count)   
    301.                     {   
    302.   
    303.                         strCol += de.Key + ",";   
    304.                     }   
    305.                     else  
    306.                     {   
    307.   
    308.                         strCol += de.Key;   
    309.                     }   
    310.                     j++;   
    311.                 }   
    312.   
    313.                 strSQL = "insert into [" + TableName + "] (" + strCol + ") values (";   
    314.                 j = 1;   
    315.                 foreach (DictionaryEntry de in htValues) //更新的字段列   
    316.                 {   
    317.                     if (j < htValues.Count)   
    318.                     {   
    319.                         strSQL += FormatColumns(de.Value) + ",";   
    320.                     }   
    321.                     else  
    322.                     {   
    323.                         strSQL += FormatColumns(de.Value) + ")";   
    324.                     }   
    325.                     j++;   
    326.   
    327.                 }   
    328.   
    329.             }   
    330.             else if (Operate.ToLower() == "update")   
    331.             {   
    332.                 strSQL = "update [" + TableName + "] set ";   
    333.                 int j = 1;   
    334.   
    335.                 foreach (DictionaryEntry de in htValues) //更新的字段列   
    336.                 {   
    337.                     if (j < htValues.Count)   
    338.                     {   
    339.                         strSQL += de.Key + "=" + FormatColumns(de.Value) + ",";   
    340.                     }   
    341.                     else  
    342.                     {   
    343.                         strSQL += de.Key + "=" + FormatColumns(de.Value);   
    344.                     }   
    345.                     j++;   
    346.                 }   
    347.                 if (WhereStr != String.Empty)   
    348.                 {   
    349.                     strSQL += " where " + WhereStr;   
    350.   
    351.                 }   
    352.   
    353.             }   
    354.             else if (Operate.ToLower() == "delete")   
    355.             {   
    356.                 strSQL = "delete from [" + TableName + "] ";   
    357.                 if (WhereStr != String.Empty)   
    358.                 {   
    359.                     strSQL += " where " + WhereStr;   
    360.   
    361.                 }   
    362.             }   
    363.             return ExecuteScalar(strSQL);   
    364.         }   
    365.   
    366.         /*识别传入的字段属于什么类型,并返回是否该字段需要带单引号*/  
    367.         /// <summary>   
    368.         /// 功能:识别传入的字段属于什么类型,并返回是否该字段需要带单引号   
    369.         /// </summary>   
    370.         /// <param name="columns">字段变量</param>   
    371.         /// <returns></returns>   
    372.         private static string FormatColumns(object columns)   
    373.         {   
    374.             string rtncolumns = "";   
    375.             switch (columns.GetType().Name.ToString())   
    376.             {   
    377.                 //整型   
    378.                 case "Int16":   
    379.                     rtncolumns = columns.ToString();   
    380.   
    381.                     break;   
    382.                 case "Int32":   
    383.                     rtncolumns = columns.ToString();   
    384.   
    385.                     break;   
    386.                 case "Int64":   
    387.                     rtncolumns = columns.ToString();   
    388.   
    389.                     break;   
    390.                 //浮点数   
    391.                 case "Double":   
    392.                     rtncolumns = columns.ToString();   
    393.   
    394.                     break;   
    395.                 case "Float":   
    396.                     rtncolumns = columns.ToString();   
    397.   
    398.                     break;   
    399.                 //字符型   
    400.                 default:   
    401.                     rtncolumns = "'" + columns.ToString() + "'";   
    402.                     break;   
    403.   
    404.             }   
    405.   
    406.             return rtncolumns;   
    407.         }  
    408.  
    409.         #region 获取根据指定字段排序并分页查询。   
    410.   
    411.         /*智能返回分页SQL语句*/  
    412.         /// <summary>   
    413.         /// 功能:智能返回分页SQL语句   
    414.         /// </summary>   
    415.         /// <param name="primaryKey">主键(不能为空)</param>   
    416.         /// <param name="queryFields">提取字段(不能为空)</param>   
    417.         /// <param name="tableName">表(理论上允许多表)</param>   
    418.         /// <param name="condition">条件(可以空)</param>   
    419.         /// <param name="OrderBy">排序,格式:字段名+""+ASC(可以空)</param>   
    420.         /// <param name="pageSize">分页数(不能为空)</param>   
    421.         /// <param name="pageIndex">当前页,起始为:1(不能为空)</param>   
    422.         /// <returns></returns>   
    423.         private static string getPageListSql(string primaryKey, string queryFields, string tableName, string condition, string orderBy, int pageSize, int pageIndex)   
    424.         {   
    425.             string strTmp = ""//---strTmp用于返回的SQL语句   
    426.             string SqlSelect = "", SqlPrimaryKeySelect = "", strOrderBy = "", strWhere = " where 1=1 ", strTop = "";   
    427.             //0:分页数量   
    428.             //1:提取字段   
    429.             //2:表   
    430.             //3:条件   
    431.             //4:主键不存在的记录   
    432.             //5:排序   
    433.             SqlSelect = " select top {0} {1} from {2} {3} {4} {5}";   
    434.             //0:主键   
    435.             //1:TOP数量,为分页数*(排序号-1)   
    436.             //2:表   
    437.             //3:条件   
    438.             //4:排序   
    439.             SqlPrimaryKeySelect = " and {0} not in (select {1} {0} from {2} {3} {4}) ";   
    440.   
    441.             if (orderBy != "")   
    442.                 strOrderBy = " order by " + orderBy;   
    443.             if (condition != "")   
    444.                 strWhere += " and " + condition;   
    445.             int pageindexsize = (pageIndex - 1) * pageSize;   
    446.             if (pageindexsize > 0)   
    447.             {   
    448.                 strTop = " top " + pageindexsize.ToString();   
    449.   
    450.                 SqlPrimaryKeySelect = String.Format(SqlPrimaryKeySelect, primaryKey, strTop, tableName, strWhere, strOrderBy);   
    451.   
    452.                 strTmp = String.Format(SqlSelect, pageSize.ToString(), queryFields, tableName, strWhere, SqlPrimaryKeySelect, strOrderBy);   
    453.   
    454.             }   
    455.             else  
    456.             {   
    457.                 strTmp = String.Format(SqlSelect, pageSize.ToString(), queryFields, tableName, strWhere, "", strOrderBy);   
    458.   
    459.             }   
    460.             return strTmp;   
    461.         }   
    462.         /*获取根据指定字段排序并分页查询。DataSet*/  
    463.         /// <summary>   
    464.         ///功能: 获取根据指定字段排序并分页查询。DataSet   
    465.         /// </summary>   
    466.         /// <param name="pageSize">每页要显示的记录的数目</param>   
    467.         /// <param name="pageIndex">要显示的页的索引</param>   
    468.         /// <param name="tableName">要查询的数据表</param>   
    469.         /// <param name="queryFields">要查询的字段,如果是全部字段请填写:*</param>   
    470.         /// <param name="primaryKey">主键字段,类似排序用到</param>   
    471.         /// <param name="orderBy">是否为升序排列:0为升序,1为降序</param>   
    472.         /// <param name="condition">查询的筛选条件</param>   
    473.         /// <returns>返回排序并分页查询的DataSet</returns>   
    474.         public static DataSet GetPageDataList(string primaryKey, string queryFields, string tableName, string condition, string orderBy, int pageSize, int pageIndex)   
    475.         {   
    476.             // ExecuteClass ec = new ExecuteClass();   
    477.   
    478.             string strSQL = getPageListSql(primaryKey, queryFields, tableName, condition, orderBy, pageSize, pageIndex);   
    479.   
    480.             return ExecuteSelectCmmond(strSQL);   
    481.         }   
    482.   
    483.         /*分页查询数据记录总数获取*/  
    484.         /// <summary>   
    485.         ///功能: 分页查询数据记录总数获取   
    486.         /// </summary>   
    487.         /// <param name="_tbName">----要显示的表或多个表的连接</param>   
    488.         /// <param name="_ID">----主表的主键</param>   
    489.         /// <param name="_strCondition">----查询条件,不需where</param>           
    490.         /// <param name="_Dist">----是否添加查询字段的 DISTINCT 默认0不添加/1添加</param>   
    491.         /// <returns></returns>   
    492.         private static string getPageListCounts(string _ID, string _tbName, string _strCondition, int _Dist)   
    493.         {   
    494.             //---存放取得查询结果总数的查询语句                       
    495.             //---对含有DISTINCT的查询进行SQL构造   
    496.             //---对含有DISTINCT的总数查询进行SQL构造   
    497.             string strTmp = "", SqlSelect = "", SqlCounts = "";   
    498.   
    499.             if (_Dist == 0)   
    500.             {   
    501.                 SqlSelect = "Select ";   
    502.                 SqlCounts = "COUNT(*)";   
    503.             }   
    504.             else  
    505.             {   
    506.                 SqlSelect = "Select DISTINCT ";   
    507.                 SqlCounts = "COUNT(DISTINCT " + _ID + ")";   
    508.             }   
    509.             if (_strCondition == string.Empty)   
    510.             {   
    511.                 strTmp = SqlSelect + " " + SqlCounts + " FROM " + _tbName;   
    512.             }   
    513.             else  
    514.             {   
    515.                 strTmp = SqlSelect + " " + SqlCounts + " FROM " + _tbName + " Where (1=1) and " + _strCondition;   
    516.             }   
    517.             return strTmp;   
    518.         }   
    519.         /*分页查询数据记录总数获取*/  
    520.         /// <summary>   
    521.         /// 功能:分页查询数据记录总数获取   
    522.         /// </summary>   
    523.         /// <param name="_tbName">----要显示的表或多个表的连接</param>   
    524.         /// <param name="_ID">----主表的主键</param>   
    525.         /// <param name="_strCondition">----查询条件,不需where</param>           
    526.         /// <param name="_Dist">----是否添加查询字段的 DISTINCT 默认0不添加/1添加</param>   
    527.         /// <returns></returns>   
    528.         public static int GetDataRecordCount(string _ID, string _tbName, string _strCondition, int _Dist)   
    529.         {   //ExecuteClass ec = new ExecuteClass();   
    530.             //  DataTable dt=new DataTable();   
    531.             string strSQL = getPageListCounts(_ID, _tbName, _strCondition, _Dist);   
    532.   
    533.   
    534.             return ExecuteScalarScalarCount(strSQL);   
    535.   
    536.   
    537.         }  
    538.         #endregion  
    539.         #endregion   
    540.     }   
    541. }   
    542.   
    543.   

    以下这段是修改数据调用方法,插入和删除都是类似的,就不一一做演示了

    c# 代码
     
    1. /*修改记录 */  
    2. /// <summary>   
    3. /// --功能:修改记录   
    4. /// </summary>   
    5. /// <param name="UserID"></param>   
    6. /// <param name="U_Name">登陆用户名</param>   
    7. /// <param name="U_PWD">登陆密码</param>   
    8. /// <param name="UserName">姓名</param>   
    9. /// <param name="EMail">邮箱</param>   
    10. /// <param name="Tel">电话</param>   
    11. /// <param name="RegDate">注册时间</param>   
    12. /// <param name="DelFlag">删除锁定标志</param>   
    13. public bool Edit(string UserID, string U_Name, string U_PWD, string UserName, string EMail, string Tel, string RegDate, string DelFlag)   
    14. {   
    15.           
    16.        bool flag = false;   
    17.     try  
    18.     {   
    19.         string tablename = "NMGE_Users";   
    20.         string where = " UserID=" + UserID;   
    21.         Hashtable ht = new Hashtable();   
    22.         if (U_Name != "")   
    23.         ht.Add("U_Name", U_Name);   
    24.         if (U_PWD != "")   
    25.             ht.Add("U_PWD", U_PWD);   
    26.         if (UserName != "")   
    27.             ht.Add("UserName", UserName);   
    28.         if (EMail != "")   
    29.             ht.Add("EMail", EMail);   
    30.         if (Tel != "")   
    31.             ht.Add("Tel", Tel);   
    32.         if (RegDate != "")   
    33.             ht.Add("RegDate", RegDate);   
    34.         if (DelFlag != "")   
    35.             ht.Add("DelFlag", DelFlag);   
    36.   
    37.   
    38.         flag = CmdSQLFactory.BuildSQLExecute(ht, where, tablename, "update");   
    39.     }   
    40.     catch (Exception ex)   
    41.     {   
    42.         PageError.showError(ex.Message);   
    43.   
    44.     }   
    45.     return flag;   
    46. }   

    以下这段是分页处理显示方法,这里用到了数据库列表控件,三种常用的数据库列表控件通用

    c# 代码
     
    1. public void GetDateListBind()   
    2. {   
    3.     string table = "NMGE_Users";   
    4.     string where = " 1=1 ";   
    5.   
    6.      
    7.     if (this.hidKeyword.Value != "")   
    8.     {   
    9.         where += " and U_Name like '%" + this.hidKeyword.Value + "%' ";   
    10.     }   
    11.           if (this.hidSortID.Value != "")   
    12.     {   
    13.         //  where += " and NewsSortID=" + this.hidSortID.Value;   
    14.     }   
    15.   
    16.   
    17.     AspNetPager1.RecordCount = CmdSQLFactory.GetDataRecordCount("UserID", table, where, 0);//统计行数   
    18.   
    19.     DataTable dtbl = CmdSQLFactory.GetPageDataList("UserID""*", table, where,“UserID desc”, AspNetPager1.PageSize, AspNetPager1.CurrentPageIndex).Tables[0];   
    20.     this.GVList.DataSource = dtbl;   
    21.     this.GVList.DataBind();   
    22.   
    23.   
    24. }   
  • 相关阅读:
    hdu--1253--胜利大逃亡(bfs)
    zzuli--2134: 维克兹的进制转换(规律)
    hdu--1316--How Many Fibs?(java大数)
    NYOJ--517--最小公倍数(大数打表)
    NYOJ--513--A+B Problem IV(大数)
    flask 重写wsgi_app实现自定义中间件
    flask的异常处理(errorhandler),template_global,以及过滤(template_filter)
    flask 的before_request以及after_request
    flask的闪现
    flask的session
  • 原文地址:https://www.cnblogs.com/ceoliujia/p/1735026.html
Copyright © 2020-2023  润新知