DbHelper通用的ADO.NET數據庫訪問幫助類

openkk 12年前發布 | 71K 次閱讀 ADO.NET 持久層框架

 通常我們在開發使用數據庫訪問幫助類時,都單獨的針對某一種數據進行編寫相應的數據訪問幫助類,如 SQLHelper,OracleHelper,OleDbHelper等,其實這些都幫助類的實現都是繼承并實現ADO.NET中的數據庫訪問基類的, 如SQLCommand->DbCommand,SQLConnection->DbConnection等,在未優化數據訪問層之前,通常 的框架結構如下所示:

DbHelper通用的ADO.NET數據庫訪問幫助類

我們現在可以將SQLServer,Oracle等的數據訪問模塊進行優化,將其合并為一個通用的DbHelper數據訪問類,優化后的訪問框架如下:

DbHelper通用的ADO.NET數據庫訪問幫助類

這樣在使用數據訪問時就可以直接使用DbHeper幫助類,這跟使用哪種數據庫無任何關系,也就是說在更換數據庫時,不需要侯任何現有的數據訪問邏輯代碼,這對我們的系統維護起到了很大的作用,在更換數據庫時,只需簡單的配置一下所使用的數據庫提供程序,如下所示:

數據庫提供程序配置操作
 <?xml version="1.0" encoding="utf-8" ?>
 <!--
 // 文 件: DbHelper.config
 // 作 者: yangdeyong
 // 時 間: 2012年4月10日 10:22:23
 // 摘 要: 結合DbHelper幫助類,對各種數據庫提供程序的配置文件,可支持Odbc、OleDb、OracleClient、SqlClient、SqlServerCe等多種數據庫提供程序
 -->
 <configuration>
   <appSettings>
     <!--一般有如下一些配置名稱 要先安裝好相應的數據庫提供程序
     System.Data.Odbc
     System.Data.OleDb
     System.Data.OracleClient
     System.Data.SqlClient
     System.Data.SqlServerCe.3.5
     iAnywhere.Data.SQLAnywhere
     -->
     <!--配置數據庫提供程序名稱 Key名稱不要更改-->
     <add key="DbProviderName" value="System.Data.SqlClient"/>

     <!--配置數據庫鏈接字段串值 Key名稱不要更改-->
     <add key="DbConnectionString" value="Data Source=localhost\SQLEXPRESS;Initial Catalog=ydyTest;Integrated Security=SSPI"/>
   </appSettings>
 </configuration>

為了滿足這一通用的數據訪問操作,我編寫了一個DbHelper.cs類庫,歡迎大家下載使用,希望可以幫助大家在數據庫訪問操作上更加方便、快捷,

具體的通用數據庫訪問幫助類代碼如下所示:

通用數據庫訪問幫助類DbHelper.cs
 // 文 件: DbHelper.cs
 // 作 者: yangdeyong
 // 時 間: 2012年4月10日 10:12:45
 // 摘 要: .NET通用數據庫操作幫助類,可支持Odbc、OleDb、OracleClient、SqlClient、SqlServerCe等多種數據庫提供程序操作

 using System;
 using System.Collections.Generic;
 using System.Data;
 using System.Data.Common;
 using System.Linq;
 using System.Text;

 namespace DbHelper
 {
     /// <summary>
     /// 說 明: .NET通用數據庫操作幫助類,可支持Odbc、OleDb、OracleClient、SqlClient、SqlServerCe等多種數據庫提供程序操作
     /// 作 者: yangdeyong
     /// 時 間: 2012-04-10 10:12:45 
     /// </summary>
     /// <remarks>
     /// 作 者: yangdeyong
     /// 時 間: 2012-04-10 10:12:45 
     /// </remarks>
     public sealed class DbHelper
     {
         #region 字段屬性

         #region 靜態公有字段
         /// <summary>
         /// 獲取當前數據庫配置的提供程序名稱值DbProviderName
         /// </summary>
         public static readonly string DbProviderName = System.Configuration.ConfigurationManager.AppSettings["DbProviderName"];

         /// <summary>
         /// 獲取當前數據庫配置的連接字符串值DbConnectionString
         /// </summary>
         public static readonly string DbConnectionString = System.Configuration.ConfigurationManager.AppSettings["DbConnectionString"];
         #endregion

         #region 私有字段
         /// <summary>
         /// 當前默認配置的數據庫提供程序DbProviderFactory
         /// </summary>
         private DbProviderFactory _dbFactory = null;

         /// <summary>
         /// 當前數據庫鏈接DbConnection對象
         /// </summary>
         private DbConnection _dbConnection = null;

         /// <summary>
         /// 當前的數據庫提供程序
         /// </summary>
         private string _dbProviderName = null;

         /// <summary>
         /// 當前的數據庫連接字符串
         /// </summary>
         private string _dbConnectionString = null;
         #endregion

         #endregion

         #region 構造函數
         /// <summary>
         /// 根據配置的數據庫提供程序和鏈接串進行初始化此對象實例
         /// </summary>
         public DbHelper()
             : this(DbHelper.DbConnectionString, DbHelper.DbProviderName)
         {
         }

         /// <summary>
         /// 根據數據庫鏈接串和數據庫提供程序名稱兩個參數進行初始化此對象實例
         /// </summary>
         /// <param name="connectionString">數據庫連接配置字符串</param>
         /// <param name="providerName">數據庫提供程序的名稱</param>
         public DbHelper(string connectionString, string providerName)
         {
             if (!string.IsNullOrEmpty(providerName))
             {
                 this._dbFactory = DbHelper.CreateDbProviderFactory(providerName);//創建默認配置的數據庫提供程序
             }
             else
             {
                 throw new ArgumentNullException("providerName", "數據庫提供程序名稱參數值不能為空,請在配置文件中配置該項值!");
             }

             if (!string.IsNullOrEmpty(connectionString))
             {
                 this._dbConnection = DbHelper.CreateDbConnection(connectionString, providerName);//創建當前數據庫鏈接對象
             }
             else
             {
                 throw new ArgumentNullException("connectionString", "數據庫鏈接串參數值不能為空,請在配置文件中配置該項值!");
             }

             //保存當前連接字符串和數據庫提供程序名稱
             this._dbConnectionString = connectionString;
             this._dbProviderName = providerName;
         }
         #endregion

         #region 方法函數

         #region 創建DbProviderFactory對象(靜態方法)
         /// <summary>
         /// 根據配置的數據庫提供程序的DbProviderName名稱來創建一個數據庫配置的提供程序DbProviderFactory對象
         /// </summary>
         public static DbProviderFactory CreateDbProviderFactory()
         {
             DbProviderFactory dbFactory = DbHelper.CreateDbProviderFactory(DbHelper.DbProviderName);

             return dbFactory;
         }

         /// <summary>
         /// 根據參數名稱創建一個數據庫提供程序DbProviderFactory對象
         /// </summary>
         /// <param name="dbProviderName">數據庫提供程序的名稱</param>
         public static DbProviderFactory CreateDbProviderFactory(string dbProviderName)
         {
             DbProviderFactory dbFactory = DbProviderFactories.GetFactory(dbProviderName);

             return dbFactory;
         }
         #endregion

         #region 創建DbConnection對象(靜態方法)
         /// <summary>
         /// 根據配置的數據庫提供程序和鏈接串來創建數據庫鏈接.
         /// </summary>
         public static DbConnection CreateDbConnection()
         {
             DbConnection dbConn = DbHelper.CreateDbConnection(DbHelper.DbConnectionString, DbHelper.DbProviderName);

             return dbConn;
         }

         /// <summary>
         /// 根據數據庫連接字符串參數來創建數據庫鏈接.
         /// </summary>
         /// <param name="connectionString">數據庫連接配置字符串</param>
         /// <param name="dbProviderName">數據庫提供程序的名稱</param>
         /// <returns></returns>
         public static DbConnection CreateDbConnection(string connectionString, string dbProviderName)
         {
             DbProviderFactory dbFactory = DbHelper.CreateDbProviderFactory(dbProviderName);

             DbConnection dbConn = dbFactory.CreateConnection();
             dbConn.ConnectionString = connectionString;

             return dbConn;
         }
         #endregion

         #region 獲取DbCommand對象
         /// <summary>
         /// 根據存儲過程名稱來構建當前數據庫鏈接的DbCommand對象
         /// </summary>
         /// <param name="storedProcedure">存儲過程名稱</param>
         public DbCommand GetStoredProcedureCommond(string storedProcedure)
         {
             DbCommand dbCmd = this._dbConnection.CreateCommand();

             dbCmd.CommandText = storedProcedure;
             dbCmd.CommandType = CommandType.StoredProcedure;

             return dbCmd;
         }

         /// <summary>
         /// 根據SQL語句來構建當前數據庫鏈接的DbCommand對象
         /// </summary>
         /// <param name="sqlQuery">SQL查詢語句</param>
         public DbCommand GetSqlStringCommond(string sqlQuery)
         {
             DbCommand dbCmd = this._dbConnection.CreateCommand();

             dbCmd.CommandText = sqlQuery;
             dbCmd.CommandType = CommandType.Text;

             return dbCmd;
         }
         #endregion

         #region 添加DbCommand參數
         /// <summary>
         /// 把參數集合添加到DbCommand對象中
         /// </summary>
         /// <param name="cmd">數據庫命令操作對象</param>
         /// <param name="dbParameterCollection">數據庫操作集合</param>
         public void AddParameterCollection(DbCommand cmd, DbParameterCollection dbParameterCollection)
         {
             if (cmd != null)
             {
                 foreach (DbParameter dbParameter in dbParameterCollection)
                 {
                     cmd.Parameters.Add(dbParameter);
                 }
             }
         }

         /// <summary>
         /// 把輸出參數添加到DbCommand對象中
         /// </summary>
         /// <param name="cmd">數據庫命令操作對象</param>
         /// <param name="parameterName">參數名稱</param>
         /// <param name="dbType">參數的類型</param>
         /// <param name="size">參數的大小</param>
         public void AddOutParameter(DbCommand cmd, string parameterName, DbType dbType, int size)
         {
             if (cmd != null)
             {
                 DbParameter dbParameter = cmd.CreateParameter();

                 dbParameter.DbType = dbType;
                 dbParameter.ParameterName = parameterName;
                 dbParameter.Size = size;
                 dbParameter.Direction = ParameterDirection.Output;

                 cmd.Parameters.Add(dbParameter);
             }
         }

         /// <summary>
         /// 把輸入參數添加到DbCommand對象中
         /// </summary>
         /// <param name="cmd">數據庫命令操作對象</param>
         /// <param name="parameterName">參數名稱</param>
         /// <param name="dbType">參數的類型</param>
         /// <param name="value">參數值</param>
         public void AddInParameter(DbCommand cmd, string parameterName, DbType dbType, object value)
         {
             if (cmd != null)
             {
                 DbParameter dbParameter = cmd.CreateParameter();

                 dbParameter.DbType = dbType;
                 dbParameter.ParameterName = parameterName;
                 dbParameter.Value = value;
                 dbParameter.Direction = ParameterDirection.Input;

                 cmd.Parameters.Add(dbParameter);
             }
         }

         /// <summary>
         /// 把返回參數添加到DbCommand對象中
         /// </summary>
         /// <param name="cmd">數據庫命令操作對象</param>
         /// <param name="parameterName">參數名稱</param>
         /// <param name="dbType">參數的類型</param>
         public void AddReturnParameter(DbCommand cmd, string parameterName, DbType dbType)
         {
             if (cmd != null)
             {
                 DbParameter dbParameter = cmd.CreateParameter();

                 dbParameter.DbType = dbType;
                 dbParameter.ParameterName = parameterName;
                 dbParameter.Direction = ParameterDirection.ReturnValue;

                 cmd.Parameters.Add(dbParameter);
             }
         }

         /// <summary>
         /// 根據參數名稱從DbCommand對象中獲取相應的參數對象
         /// </summary>
         /// <param name="cmd">數據庫命令操作對象</param>
         /// <param name="parameterName">參數名稱</param>
         public DbParameter GetParameter(DbCommand cmd, string parameterName)
         {
             if (cmd != null && cmd.Parameters.Count > 0)
             {
                 DbParameter param = cmd.Parameters[parameterName];

                 return param;
             }

             return null;
         }
         #endregion

         #region 執行SQL腳本語句
         /// <summary>
         /// 執行相應的SQL命令,返回一個DataSet數據集合
         /// </summary>
         /// <param name="sqlQuery">需要執行的SQL語句</param>
         /// <returns>返回一個DataSet數據集合</returns>
         public DataSet ExecuteDataSet(string sqlQuery)
         {
             DataSet ds = new DataSet();

             if (!string.IsNullOrEmpty(sqlQuery))
             {
                 DbCommand cmd = GetSqlStringCommond(sqlQuery);

                 ds = ExecuteDataSet(cmd);
             }

             return ds;
         }

         /// <summary>
         /// 執行相應的SQL命令,返回一個DataTable數據集
         /// </summary>
         /// <param name="sqlQuery">需要執行的SQL語句</param>
         /// <returns>返回一個DataTable數據集</returns>
         public DataTable ExecuteDataTable(string sqlQuery)
         {
             DataTable dt = new DataTable();

             if (!string.IsNullOrEmpty(sqlQuery))
             {
                 DbCommand cmd = GetSqlStringCommond(sqlQuery);

                 dt = ExecuteDataTable(cmd);
             }

             return dt;
         }

         /// <summary>
         /// 執行相應的SQL命令,返回一個DbDataReader數據對象,如果沒有則返回null值
         /// </summary>
         /// <param name="sqlQuery">需要執行的SQL命令</param>
         /// <returns>返回一個DbDataReader數據對象,如果沒有則返回null值</returns>
         public DbDataReader ExecuteReader(string sqlQuery)
         {
             if (!string.IsNullOrEmpty(sqlQuery))
             {
                 DbCommand cmd = GetSqlStringCommond(sqlQuery);

                 DbDataReader reader = ExecuteReader(cmd);

                 return reader;
             }

             return null;
         }

         /// <summary>
         /// 執行相應的SQL命令,返回影響的數據記錄數,如果不成功則返回-1
         /// </summary>
         /// <param name="sqlQuery">需要執行的SQL命令</param>
         /// <returns>返回影響的數據記錄數,如果不成功則返回-1</returns>
         public int ExecuteNonQuery(string sqlQuery)
         {
             if (!string.IsNullOrEmpty(sqlQuery))
             {
                 DbCommand cmd = GetSqlStringCommond(sqlQuery);

                 int retVal = ExecuteNonQuery(cmd);

                 return retVal;
             }

             return -1;
         }

         /// <summary>
         /// 執行相應的SQL命令,返回結果集中的第一行第一列的值,如果不成功則返回null值
         /// </summary>
         /// <param name="sqlQuery">需要執行的SQL命令</param>
         /// <returns>返回結果集中的第一行第一列的值,如果不成功則返回null值</returns>
         public object ExecuteScalar(string sqlQuery)
         {
             if (!string.IsNullOrEmpty(sqlQuery))
             {
                 DbCommand cmd = GetSqlStringCommond(sqlQuery);

                 object retVal = ExecuteScalar(cmd);

                 return retVal;
             }

             return null;
         }

         #endregion

         #region 執行DbCommand命令
         /// <summary>
         /// 執行相應的命令,返回一個DataSet數據集合
         /// </summary>
         /// <param name="cmd">需要執行的DbCommand命令對象</param>
         /// <returns>返回一個DataSet數據集合</returns>
         public DataSet ExecuteDataSet(DbCommand cmd)
         {
             DataSet ds = new DataSet();

             if (cmd != null)
             {
                 DbDataAdapter dbDataAdapter = this._dbFactory.CreateDataAdapter();
                 dbDataAdapter.SelectCommand = cmd;

                 dbDataAdapter.Fill(ds);
             }

             return ds;
         }

         /// <summary>
         /// 執行相應的命令,返回一個DataTable數據集合
         /// </summary>
         /// <param name="cmd">需要執行的DbCommand命令對象</param>
         /// <returns>返回一個DataTable數據集合</returns>
         public DataTable ExecuteDataTable(DbCommand cmd)
         {
             DataTable dataTable = new DataTable();

             if (cmd != null)
             {
                 DbDataAdapter dbDataAdapter = this._dbFactory.CreateDataAdapter();
                 dbDataAdapter.SelectCommand = cmd;

                 dbDataAdapter.Fill(dataTable);
             }

             return dataTable;
         }

         /// <summary>
         /// 執行相應的命令,返回一個DbDataReader數據對象,如果沒有則返回null值
         /// </summary>
         /// <param name="cmd">需要執行的DbCommand命令對象</param>
         /// <returns>返回一個DbDataReader數據對象,如果沒有則返回null值</returns>
         public DbDataReader ExecuteReader(DbCommand cmd)
         {
             if (cmd != null && cmd.Connection != null)
             {
                 if (cmd.Connection.State != ConnectionState.Open)
                 {
                     cmd.Connection.Open();
                 }

                 DbDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);//當reader讀取結束時自動關閉數據庫鏈接

                 return reader;
             }

             return null;
         }

         /// <summary>
         /// 執行相應的命令,返回影響的數據記錄數,如果不成功則返回-1
         /// </summary>
         /// <param name="cmd">需要執行的DbCommand命令對象</param>
         /// <returns>返回影響的數據記錄數,如果不成功則返回-1</returns>
         public int ExecuteNonQuery(DbCommand cmd)
         {
             if (cmd != null && cmd.Connection != null)
             {
                 if (cmd.Connection.State != ConnectionState.Open)
                 {
                     cmd.Connection.Open();
                 }

                 int retVal = cmd.ExecuteNonQuery();

                 cmd.Connection.Close();

                 return retVal;
             }

             return -1;
         }

         /// <summary>
         /// 執行相應的命令,返回結果集中的第一行第一列的值,如果不成功則返回null值
         /// </summary>
         /// <param name="cmd">需要執行的DbCommand命令對象</param>
         /// <returns>返回結果集中的第一行第一列的值,如果不成功則返回null值</returns>
         public object ExecuteScalar(DbCommand cmd)
         {
             if (cmd != null && cmd.Connection != null)
             {
                 if (cmd.Connection.State != ConnectionState.Open)
                 {
                     cmd.Connection.Open();
                 }

                 object retVal = cmd.ExecuteScalar();

                 cmd.Connection.Close();

                 return retVal;
             }

             return null;
         }
         #endregion

         #region 執行DbTransaction事務
         /// <summary>
         /// 以事務的方式執行相應的命令,返回一個DataSet數據集合
         /// </summary>
         /// <param name="cmd">需要執行的DbCommand命令對象</param>
         /// <param name="trans">數據庫事務對象</param>
         /// <returns>返回一個DataSet數據集合</returns>
         public DataSet ExecuteDataSet(DbCommand cmd, Trans trans)
         {
             DataSet ds = new DataSet();

             if (cmd != null)
             {
                 cmd.Connection = trans.Connection;
                 cmd.Transaction = trans.Transaction;

                 DbDataAdapter dbDataAdapter = this._dbFactory.CreateDataAdapter();
                 dbDataAdapter.SelectCommand = cmd;

                 dbDataAdapter.Fill(ds);
             }

             return ds;
         }

         /// <summary>
         /// 以事務的方式執行相應的命令,返回一個DataTable數據集合
         /// </summary>
         /// <param name="cmd">需要執行的DbCommand命令對象</param>
         /// <param name="trans">數據庫事務對象</param>
         /// <returns>返回一個DataTable數據集合</returns>
         public DataTable ExecuteDataTable(DbCommand cmd, Trans trans)
         {
             DataTable dataTable = new DataTable();

             if (cmd != null)
             {
                 cmd.Connection = trans.Connection;
                 cmd.Transaction = trans.Transaction;

                 DbDataAdapter dbDataAdapter = this._dbFactory.CreateDataAdapter();
                 dbDataAdapter.SelectCommand = cmd;

                 dbDataAdapter.Fill(dataTable);
             }

             return dataTable;
         }

         /// <summary>
         /// 以事務的方式執行相應的命令,返回一個DbDataReader數據對象,如果沒有則返回null值
         /// </summary>
         /// <param name="cmd">需要執行的DbCommand命令對象</param>
         /// <param name="trans">數據庫事務對象</param>
         /// <returns>返回一個DbDataReader數據對象,如果沒有則返回null值</returns>
         public DbDataReader ExecuteReader(DbCommand cmd, Trans trans)
         {
             if (cmd != null)
             {
                 cmd.Connection.Close();

                 cmd.Connection = trans.Connection;
                 cmd.Transaction = trans.Transaction;

                 DbDataReader reader = cmd.ExecuteReader();

                 return reader;
             }

             return null;
         }

         /// <summary>
         /// 以事務的方式執行相應的命令,返回影響的數據記錄數,如果不成功則返回-1
         /// </summary>
         /// <param name="cmd">需要執行的DbCommand命令對象</param>
         /// <param name="trans">數據庫事務對象</param>
         /// <returns>返回影響的數據記錄數,如果不成功則返回-1</returns>
         public int ExecuteNonQuery(DbCommand cmd, Trans trans)
         {
             if (cmd != null)
             {
                 cmd.Connection.Close();

                 cmd.Connection = trans.Connection;
                 cmd.Transaction = trans.Transaction;

                 int retVal = cmd.ExecuteNonQuery();

                 return retVal;
             }

             return -1;
         }

         /// <summary>
         /// 以事務的方式執行相應的命令,返回結果集中的第一行第一列的值,如果不成功則返回null值
         /// </summary>
         /// <param name="cmd">需要執行的DbCommand命令對象</param>
         /// <param name="trans">數據庫事務對象</param>
         /// <returns>返回結果集中的第一行第一列的值,如果不成功則返回null值</returns>
         public object ExecuteScalar(DbCommand cmd, Trans trans)
         {
             if (cmd != null)
             {
                 cmd.Connection.Close();

                 cmd.Connection = trans.Connection;
                 cmd.Transaction = trans.Transaction;

                 object retVal = cmd.ExecuteScalar();

                 return retVal;
             }

             return null;
         }
         #endregion

         #endregion
     }

     /// <summary>
     /// 說 明: 數據庫事務操作對象
     /// 作 者: yangdeyong
     /// 時 間: 2012-04-10 10:19:23 
     /// </summary>
     /// <remarks>
     /// 作 者: yangdeyong
     /// 時 間: 2012-04-10 10:12:45 
     /// </remarks>
     public sealed class Trans : IDisposable
     {
         #region 字段屬性
         private DbConnection connection = null;
         /// <summary>
         /// 獲取當前數據庫鏈接對象
         /// </summary>
         public DbConnection Connection
         {
             get
             {
                 return this.connection;
             }
         }

         private DbTransaction transaction = null;
         /// <summary>
         /// 獲取當前數據庫事務對象
         /// </summary>
         public DbTransaction Transaction
         {
             get
             {
                 return this.transaction;
             }
         }
         #endregion

         #region 構造函數
         /// <summary>
         /// 根據配置的數據庫提供程序和連接字符串來創建此事務對象
         /// </summary>
         public Trans()
             : this(DbHelper.DbConnectionString, DbHelper.DbProviderName)
         {
         }

         /// <summary>
         /// 根據數據庫連接字符串來創建此事務對象
         /// </summary>
         /// <param name="connectionString">數據庫連接字符串</param>
         /// <param name="dbProviderName">數據庫提供程序的名稱</param>
         public Trans(string connectionString, string dbProviderName)
         {
             if (!string.IsNullOrEmpty(connectionString))
             {
                 this.connection = DbHelper.CreateDbConnection(connectionString, dbProviderName);
                 this.Connection.Open();

                 this.transaction = this.Connection.BeginTransaction();
             }
             else
             {
                 throw new ArgumentNullException("connectionString", "數據庫鏈接串參數值不能為空!");
             }
         }
         #endregion

         #region 方法函數
         /// <summary>
         /// 提交此數據庫事務操作
         /// </summary>
         public void Commit()
         {
             this.Transaction.Commit();

             this.Close();
         }

         /// <summary>
         /// 回滾此數據庫事務操作
         /// </summary>
         public void RollBack()
         {
             this.Transaction.Rollback();

             this.Close();
         }

         /// <summary>
         /// 關閉此數據庫事務鏈接
         /// </summary>
         public void Close()
         {
             if (this.Connection.State != System.Data.ConnectionState.Closed)
             {
                 this.Connection.Close();
             }
         }
         #endregion

         #region IDisposable 成員
         /// <summary>
         /// 執行與釋放或重置非托管資源相關的應用程序定義的任務。
         /// </summary>
         public void Dispose()
         {
             this.Close();
         }
         #endregion
     }
 }
在這些代碼中,可以滿足大多數的數據訪問操作,如果需要自己還可以再繼續擴展的,也歡迎大家指出其中存在的不足之處,謝謝。
轉自:http://www.cnblogs.com/youngdy/archive/2012/06/14/DbHelper.html

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!