前情提要
有時候我們會在朋友圈看到如下兩種轉發情況:一種是前面帶縮略圖的 ,一種是無縮略圖的,當然有縮略圖的不管是從用戶體驗,還是網站推廣運營方都是更優的選擇。
那我們看看微信分享朋友圈縮略圖是 怎么一回事呢
注:微信6.5.5版本后,微信調整了分享規則。以前的沒有通過認證公眾號jssdk注入分享的都不是官方認可的分享。
必要前提:① 所打開的分享網頁 域名必須經過備案(備案過的二級域名也行) ②公眾號后台基本配置里面獲取AppID和AppSecret 以添加服務器IP到白名單 顯示如下:
代碼實現
在HTML的Body下 加入如下代碼:
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <script> var dataForWeixin = { appId: '@ViewBag.appid', url: '@ViewBag.url', jsapiTicket:'@ViewBag.jsapiTicket', title: '轉發標題', imgUrl: '服務器上需要顯示的圖片路徑', timestamp: '@ViewBag.timestamp', nonceStr: '@ViewBag.nonceStr', signature: '@ViewBag.signature', jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage'], callback: function () { } }; wx.config({ debug: false, appId: dataForWeixin.appId, timestamp: dataForWeixin.timestamp, nonceStr: dataForWeixin.nonceStr, signature: dataForWeixin.signature, jsApiList: dataForWeixin.jsApiList }); </script> <div style="height:0px;overflow:hidden;"> <img src="服務器上需要顯示的圖片路徑" /> </div>
在控制器中加入一個 獲取微信分享接口的參數如下(再程序入口調用此方法即可)
/// <summary> /// 獲取微信分享接口參數 /// </summary> public void GetWX() { string app_id = ConfigHelper.AppId; string AppSecret = ConfigHelper.AppSecret; writeLog.WriteLogs("app_id,AppSecret:" + app_id + AppSecret + ""); Wx_helper jssdk = new Wx_helper(app_id, AppSecret); Hashtable ht = jssdk.getSignPackage(); // 遍歷哈希表 foreach (DictionaryEntry de in ht) { if (de.Key.ToString() == "appId") { ViewBag.appid = de.Value.ToString(); } if (de.Key.ToString() == "nonceStr") { ViewBag.nonceStr = de.Value.ToString(); } if (de.Key.ToString() == "timestamp") { ViewBag.timestamp = de.Value.ToString(); } if (de.Key.ToString() == "url") { ViewBag.url = de.Value.ToString(); } if (de.Key.ToString() == "signature") { ViewBag.signature = de.Value.ToString(); } if (de.Key.ToString() == "jsapiTicket") { ViewBag.jsapiTicket = de.Value.ToString(); } } }
上述代碼中 Wx_helper(微信接口類)如下:
/// <summary> /// 微信接口類 /// </summary> public class Wx_helper : DBBase { private string appId; private string appSecret; private DataTable DT; public Wx_helper(string appId, string appSecret) { this.appId = appId; this.appSecret = appSecret; } //得到數據包,返回使用頁面 public System.Collections.Hashtable getSignPackage() { string jsapiTicket = getJsApiTicket(); string url_req = HttpContext.Current.Request.Url.ToString(); //當前網頁的URL string pageurl = HttpContext.Current.Request.Url.AbsoluteUri; writeLog.WriteLogs("當前網頁的URL:" + pageurl + ""); //string url = "http://" + HttpContext.Current.Request.ServerVariables["Http_Host"] + HttpContext.Current.Request.ApplicationPath; string timestamp = Convert.ToString(ConvertDateTimeInt(DateTime.Now)); string nonceStr = createNonceStr(); // 這里參數的順序要按照 key 值 ASCII 碼升序排序 string rawstring = "jsapi_ticket=" + jsapiTicket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + pageurl + ""; writeLog.WriteLogs("rawstring:" + rawstring + ""); string signature = SHA1_Hash(rawstring); System.Collections.Hashtable signPackage = new System.Collections.Hashtable(); signPackage.Add("appId", appId); signPackage.Add("nonceStr", nonceStr); signPackage.Add("timestamp", timestamp); signPackage.Add("url", pageurl); signPackage.Add("signature", signature); signPackage.Add("jsapiTicket", jsapiTicket); return signPackage; } //創建隨機字符串 private string createNonceStr() { int length = 16; string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; string str = ""; Random rad = new Random(); for (int i = 0; i < length; i++) { str += chars.Substring(rad.Next(0, chars.Length - 1), 1); } return str; } //SHA1哈希加密算法 public string SHA1_Hash(string str_sha1_in) { SHA1 sha1 = new SHA1CryptoServiceProvider(); byte[] bytes_sha1_in = System.Text.UTF8Encoding.Default.GetBytes(str_sha1_in); byte[] bytes_sha1_out = sha1.ComputeHash(bytes_sha1_in); string str_sha1_out = BitConverter.ToString(bytes_sha1_out); str_sha1_out = str_sha1_out.Replace("-", "").ToLower(); return str_sha1_out; } //得到ticket 如果文件里時間 超時則重新獲取 private string getJsApiTicket() { //這里我從數據庫讀取 string strSql = "select jsapi_ticket,ticket_expires,add_time from dt_weixin_jsapiticket where ID=1"; DataSet ds = sqlhelp.ExecuteDataSet(strSql); DT = ds.Tables[0]; int expire_time = Convert.ToInt32(DT.Rows[0]["ticket_expires"]); string ticket = DT.Rows[0]["jsapi_ticket"].ToString(); string error = string.Empty; string accessToken = new WXCRMComm().GetAccessToken(out error); //獲取系統的全局token writeLog.WriteLogs("獲取系統的全局token :" + accessToken + "," + error + ""); if (string.IsNullOrEmpty(error)) { writeLog.WriteLogs("GetAccessToken:" + error + ""); //計算時間判斷是否過期 TimeSpan ts = DateTime.Now - DateTime.Parse(DT.Rows[0]["add_time"].ToString()); double chajunSecond = ts.TotalSeconds; if (chajunSecond >= 1200) { writeLog.WriteLogs("jsapiticket計算時間判斷是否過期:已過期"); string url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi"; Jsapi api = JsonConvert.DeserializeObject<Jsapi>(httpGet(url)); ticket = api.ticket; if (ticket != "") { expire_time = ConvertDateTimeInt(DateTime.Now) + 1200; //存入數據庫操作 strSql = " update dt_weixin_jsapiticket set jsapi_ticket='" + ticket + "',ticket_expires='" + expire_time + "',add_time='" + DateTime.Now + "' where ID=1"; sqlhelp.ExecuteNonQuery(strSql); } } writeLog.WriteLogs("jsapiticket計算時間判斷是否過期:沒過期"); } return ticket; } /// <summary> /// 將c# DateTime時間格式轉換為Unix時間戳格式 /// </summary> /// <param name="time">時間</param> /// <returns>double</returns> public int ConvertDateTimeInt(System.DateTime time) { int intResult = 0; System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); intResult = Convert.ToInt32((time - startTime).TotalSeconds); return intResult; } //發起一個http請球,返回值 private string httpGet(string url) { try { WebClient MyWebClient = new WebClient(); MyWebClient.Credentials = CredentialCache.DefaultCredentials;//獲取或設置用於向Internet資源的請求進行身份驗證的網絡憑據 Byte[] pageData = MyWebClient.DownloadData(url); //從指定網站下載數據 string pageHtml = System.Text.Encoding.Default.GetString(pageData); //如果獲取網站頁面采用的是GB2312,則使用這句 return pageHtml; } catch (WebException webEx) { Console.WriteLine(webEx.Message.ToString()); return null; } } #region 創建Json序列化 及反序列化類目 // /// <summary> /// 創建JSon類 保存文件 jsapi_ticket.json /// </summary> public class JSTicket { public string jsapi_ticket { get; set; } public double expire_time { get; set; } } /// <summary> /// 創建 JSon類 保存文件 access_token.json /// </summary> public class AccToken { public string access_token { get; set; } public double expires_in { get; set; } } /// <summary> /// 創建從微信返回結果的一個類 用於獲取ticket /// </summary> public class Jsapi { public int errcode { get; set; } public string errmsg { get; set; } public string ticket { get; set; } public string expires_in { get; set; } } #endregion }
上述代碼中負責獲取和刷新的 WXCRMComm 類如下:
/// <summary> /// 負責獲取或刷新AccessToken /// </summary> public class WXCRMComm { public WXCRMComm() { } private string appid; private string appsecret; BLLweixin_access_token tokenBLL = new BLL.BLLweixin_access_token(); //賬戶AccessToken 此處根據自己項目單獨特別處理 BLLweixin_account accountBLL = new BLL.BLLweixin_account(); //公眾平台賬戶 此處根據自己項目單獨特別處理 /// <summary> /// 及時獲得access_token值 /// access_token是公眾號的全局唯一票據,公眾號調用各接口時都需使用access_token。正常情況下access_token有效期為7200秒, /// 重復獲取將導致上次獲取的access_token失效。 /// 每日限額獲取access_token.我們將access_token保存到數據庫里,間隔時間為20分鍾,從微信公眾平台獲得一次。 /// </summary> public string GetAccessToken(out string error) { string access_token = string.Empty; error = string.Empty; try { Model.weixin_account accountModel = accountBLL.GetModel(); //公眾平台賬戶信息 if (accountModel == null || string.IsNullOrEmpty(accountModel.appid) || string.IsNullOrEmpty(accountModel.appsecret)) { error = "AppId或者AppSecret未填寫,請在補全信息!"; return string.Empty; } //沒有找到該賬戶則獲取AccessToKen寫入存儲1200秒 if (!tokenBLL.Exists()) { var result = Senparc.Weixin.MP.CommonAPIs.CommonApi.GetToken(accountModel.appid, accountModel.appsecret); access_token = result.access_token; tokenBLL.Add(access_token); return access_token; } //獲取公眾賬戶的實體 Model.weixin_access_token tokenModel = tokenBLL.GetModel(); //計算時間判斷是否過期 TimeSpan ts = DateTime.Now - tokenModel.add_time; double chajunSecond = ts.TotalSeconds; if (string.IsNullOrEmpty(tokenModel.access_token) || chajunSecond >= tokenModel.expires_in) { writeLog.WriteLogs("GetAccessToken:重新修改"); //從微信平台重新獲得AccessToken var result = Senparc.Weixin.MP.CommonAPIs.CommonApi.GetToken(accountModel.appid, accountModel.appsecret); access_token = result.access_token; //更新到數據庫里的AccessToken tokenModel.access_token = access_token; tokenModel.add_time = DateTime.Now; bool ret=tokenBLL.Update(tokenModel); writeLog.WriteLogs("GetAccessToken:重新修改"+ ret + ""); } else { writeLog.WriteLogs("GetAccessToken:獲取舊的"); access_token = tokenModel.access_token; } } catch (Exception ex) { error = "獲取AccessToken出錯:" + ex.Message; } return access_token; } /// <summary> ///【強制刷新】access_token值 /// access_token是公眾號的全局唯一票據,公眾號調用各接口時都需使用access_token。正常情況下access_token有效期為7200秒, /// 重復獲取將導致上次獲取的access_token失效。 /// 每日限額獲取access_token.我們將access_token保存到數據庫里,間隔時間為20分鍾,從微信公眾平台獲得一次。 /// </summary> /// <returns></returns> public string FlushAccessToken(out string error) { string access_token = string.Empty; error = string.Empty; try { Model.weixin_account accountModel = accountBLL.GetModel(); //公眾平台賬戶信息 if (string.IsNullOrEmpty(accountModel.appid) || string.IsNullOrEmpty(accountModel.appsecret)) { error = "AppId或者AppSecret未填寫,請在補全信息!"; return ""; } var result = Senparc.Weixin.MP.CommonAPIs.CommonApi.GetToken(accountModel.appid, accountModel.appsecret); access_token = result.access_token; //沒有找到該賬戶則獲取AccessToKen寫入存儲1200秒 if (!tokenBLL.Exists()) { tokenBLL.Add(access_token); } else { //獲取公眾賬戶的實體 Model.weixin_access_token tokenModel = tokenBLL.GetModel(); //更新到數據庫里的AccessToken tokenModel.access_token = access_token; tokenModel.add_time = DateTime.Now; tokenBLL.Update(tokenModel); } } catch (Exception ex) { error = "獲得AccessToken出錯:" + ex.Message; } return access_token; } /// <summary> /// 獲得所有關注用戶的openid字符串(別的方法調用此方法) /// </summary> private IList<string> BaseUserOpenId(out string error) { IList<string> ret = new List<string>(); string access_token = GetAccessToken(out error); if (error != "") { return null; } Senparc.Weixin.MP.AdvancedAPIs.User.OpenIdResultJson openidJson = Senparc.Weixin.MP.AdvancedAPIs.UserApi.Get(access_token, string.Empty); if (openidJson.count == openidJson.total) { ret = openidJson.data.openid; } else { GetNextUserOpenId(openidJson.next_openid, ret); } return ret; } /// <summary> /// (基礎方法)獲得所有關注用戶的openid字符串(遞歸算法) /// </summary> private void GetNextUserOpenId(string nexOpenid, IList<string> openidList) { string err = string.Empty; string access_token = GetAccessToken(out err); Senparc.Weixin.MP.AdvancedAPIs.User.OpenIdResultJson openidJson = Senparc.Weixin.MP.AdvancedAPIs.UserApi.Get(access_token, nexOpenid); if (openidJson == null || openidJson.count <= 0) { return; } else { for (int i = 0; i < openidJson.data.openid.Count; i++) { openidList.Add(openidJson.data.openid[i]); } GetNextUserOpenId(openidJson.next_openid, openidList); } } #region 消息群發處理=================================== /// <summary> /// 上傳永久素材 /// </summary> public string UploadForeverMedia(string imgFullPath, out string error) { string accessToken = GetAccessToken(out error); if (!string.IsNullOrEmpty(error)) { return string.Empty; } var result = Senparc.Weixin.MP.AdvancedAPIs.MediaApi.UploadForeverMedia(accessToken, imgFullPath); if (result.errcode == 0) { return result.media_id; } error = result.errmsg; return string.Empty; } /// <summary> /// 刪除永久素材 /// </summary> public bool DeleteForeverMedia(string mediaId, out string error) { string accessToken = GetAccessToken(out error); if (!string.IsNullOrEmpty(error)) { return false; } var result = Senparc.Weixin.MP.AdvancedAPIs.MediaApi.DeleteForeverMedia(accessToken, mediaId); if (result.errcode != 0) { error = result.errmsg; return false; } error = string.Empty; return true; } /// <summary> /// 群發消息 /// </summary> public bool SendGroupMessageByGroupId(List<Senparc.Weixin.MP.AdvancedAPIs.GroupMessage.NewsModel> ls, out string error) { string accessToken = GetAccessToken(out error); //新增素材 var result1 = Senparc.Weixin.MP.AdvancedAPIs.MediaApi.UploadNews(accessToken, 10000, ls.ToArray()); if (result1.errcode != 0) { error = result1.errmsg; return false; } //群發消息 var result2 = Senparc.Weixin.MP.AdvancedAPIs.GroupMessageApi.SendGroupMessageByGroupId(accessToken, "0", result1.media_id, Senparc.Weixin.MP.GroupMessageType.mpnews, true); if (result2.errcode != 0) { error = result2.errmsg; return false; } error = string.Empty; return true; } #endregion }
另外,微信接口類 繼承 了 DBBase ,里面只有連接數據庫對象,這個可以根據自己項目特點和需要處理 這里只做演示:
public class DBBase { protected static string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; public SqlHelper sqlhelp = new SqlHelper(connectionString); }
上述代碼中SqlHelper 通用幫助類 也貼一下吧,僅供參考

/// <summary> /// SqlHelper操作類 /// </summary> public sealed partial class SqlHelper { /// <summary> /// 批量操作每批次記錄數 /// </summary> public static int BatchSize = 2000; /// <summary> /// 超時時間 /// </summary> public static int CommandTimeOut = 600; /// <summary> ///初始化SqlHelper實例 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> public SqlHelper(string connectionString) { this.ConnectionString = connectionString; } /// <summary> /// 數據庫連接字符串 /// </summary> public string ConnectionString { get; set; } #region 實例方法 #region ExecuteNonQuery /// <summary> /// 執行SQL語句,返回影響的行數 /// </summary> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回影響的行數</returns> public int ExecuteNonQuery(string commandText, params SqlParameter[] parms) { return ExecuteNonQuery(ConnectionString, CommandType.Text, commandText, parms); } /// <summary> /// 執行SQL語句,返回影響的行數 /// </summary> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回影響的行數</returns> public int ExecuteNonQuery(CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteNonQuery(ConnectionString, commandType, commandText, parms); } #endregion ExecuteNonQuery #region ExecuteScalar /// <summary> /// 執行SQL語句,返回結果集中的第一行第一列 /// </summary> /// <typeparam name="T">返回對象類型</typeparam> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一行第一列</returns> public T ExecuteScalar<T>(string commandText, params SqlParameter[] parms) { return ExecuteScalar<T>(ConnectionString, commandText, parms); } /// <summary> /// 執行SQL語句,返回結果集中的第一行第一列 /// </summary> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一行第一列</returns> public object ExecuteScalar(string commandText, params SqlParameter[] parms) { return ExecuteScalar(ConnectionString, CommandType.Text, commandText, parms); } /// <summary> /// 執行SQL語句,返回結果集中的第一行第一列 /// </summary> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一行第一列</returns> public object ExecuteScalar(CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteScalar(ConnectionString, commandType, commandText, parms); } #endregion ExecuteScalar #region ExecuteDataReader /// <summary> /// 執行SQL語句,返回只讀數據集 /// </summary> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回只讀數據集</returns> private SqlDataReader ExecuteDataReader(string commandText, params SqlParameter[] parms) { return ExecuteDataReader(ConnectionString, CommandType.Text, commandText, parms); } /// <summary> /// 執行SQL語句,返回只讀數據集 /// </summary> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回只讀數據集</returns> private SqlDataReader ExecuteDataReader(CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteDataReader(ConnectionString, commandType, commandText, parms); } #endregion #region ExecuteDataRow /// <summary> /// 執行SQL語句,返回結果集中的第一行 /// </summary> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一行</returns> public DataRow ExecuteDataRow(string commandText, params SqlParameter[] parms) { return ExecuteDataRow(ConnectionString, CommandType.Text, commandText, parms); } /// <summary> /// 執行SQL語句,返回結果集中的第一行 /// </summary> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一行</returns> public DataRow ExecuteDataRow(CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteDataRow(ConnectionString, commandType, commandText, parms); } #endregion ExecuteDataRow #region ExecuteDataTable /// <summary> /// 執行SQL語句,返回結果集中的第一個數據表 /// </summary> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一個數據表</returns> public DataTable ExecuteDataTable(string commandText, params SqlParameter[] parms) { return ExecuteDataTable(ConnectionString, CommandType.Text, commandText, parms); } /// <summary> /// 執行SQL語句,返回結果集中的第一個數據表 /// </summary> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一個數據表</returns> public DataTable ExecuteDataTable(CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteDataSet(ConnectionString, commandType, commandText, parms).Tables[0]; } /// <summary> /// 執行SQL語句,返回結果集中的第一個數據表 /// </summary> /// <param name="sql">SQL語句</param> /// <param name="order">排序SQL,如"ORDER BY ID DESC"</param> /// <param name="pageSize">每頁記錄數</param> /// <param name="pageIndex">頁索引</param> /// <param name="parms">查詢參數</param> /// <param name="query">查詢SQL</param> /// <returns></returns> public DataTable ExecutePageDataTable(string sql, string order, int pageSize, int pageIndex, SqlParameter[] parms = null, string query = null, string cte = null) { return ExecutePageDataTable(sql, order, pageSize, pageIndex, parms, query, cte); } #endregion ExecuteDataTable #region ExecuteDataSet /// <summary> /// 執行查詢語句,返回DataSet /// </summary> /// <param name="SQLString">查詢語句</param> /// <returns>DataSet</returns> public DataSet ExecuteDataSet(string SQLString) { return ExecuteDataSet(SQLString, ConnectionString); } /// <summary> /// 執行SQL語句,返回結果集 /// </summary> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集</returns> public DataSet ExecuteDataSet(string commandText, params SqlParameter[] parms) { return ExecuteDataSet(ConnectionString, CommandType.Text, commandText, parms); } /// <summary> /// 執行SQL語句,返回結果集 /// </summary> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集</returns> public DataSet ExecuteDataSet(CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteDataSet(ConnectionString, commandType, commandText, parms); } public object GetSingle(string SQLString, params SqlParameter[] cmdParms) { return GetSingle(SQLString, ConnectionString, cmdParms); } #endregion ExecuteDataSet #region 批量操作 /// <summary> /// 大批量數據插入 /// </summary> /// <param name="table">數據表</param> public void BulkInsert(DataTable table) { BulkInsert(ConnectionString, table); } /// <summary> /// 使用MySqlDataAdapter批量更新數據 /// </summary> /// <param name="table">數據表</param> public void BatchUpdate(DataTable table) { BatchUpdate(ConnectionString, table); } /// <summary> /// 分批次批量刪除數據 /// </summary> /// <param name="sql">SQL語句</param> /// <param name="batchSize">每批次刪除記錄行數</param> /// <param name="interval">批次執行間隔(秒)</param> public void BatchDelete(string sql, int batchSize = 1000, int interval = 1) { BatchDelete(ConnectionString, sql, batchSize, interval); } /// <summary> /// 分批次批量更新數據 /// </summary> /// <param name="sql">SQL語句</param> /// <param name="batchSize">每批次更新記錄行數</param> /// <param name="interval">批次執行間隔(秒)</param> public void BatchUpdate(string sql, int batchSize = 1000, int interval = 1) { BatchUpdate(ConnectionString, sql, batchSize, interval); } #endregion 批量操作 #endregion 實例方法 #region 靜態方法 public static object GetSingle(string SQLString, string connectionString, params SqlParameter[] cmdParms) { using (SqlConnection connection = new SqlConnection(connectionString)) { using (SqlCommand cmd = new SqlCommand()) { try { PrepareCommand(cmd, connection, null, SQLString, cmdParms); object obj = cmd.ExecuteScalar(); cmd.Parameters.Clear(); if ((Object.Equals(obj, null)) || (Object.Equals(obj, System.DBNull.Value))) { return null; } else { return obj; } } catch (System.Data.SqlClient.SqlException e) { throw e; } } } } private static void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, string cmdText, SqlParameter[] cmdParms) { if (conn.State != ConnectionState.Open) conn.Open(); cmd.Connection = conn; cmd.CommandText = cmdText; if (trans != null) cmd.Transaction = trans; cmd.CommandType = CommandType.Text;//cmdType; if (cmdParms != null) { foreach (SqlParameter parameter in cmdParms) { if ((parameter.Direction == ParameterDirection.InputOutput || parameter.Direction == ParameterDirection.Input) && (parameter.Value == null)) { parameter.Value = DBNull.Value; } cmd.Parameters.Add(parameter); } } } private static void PrepareCommand(SqlCommand command, SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] parms) { if (connection.State != ConnectionState.Open) connection.Open(); command.Connection = connection; command.CommandTimeout = CommandTimeOut; // 設置命令文本(存儲過程名或SQL語句) command.CommandText = commandText; // 分配事務 if (transaction != null) { command.Transaction = transaction; } // 設置命令類型. command.CommandType = commandType; if (parms != null && parms.Length > 0) { //預處理SqlParameter參數數組,將為NULL的參數賦值為DBNull.Value; foreach (SqlParameter parameter in parms) { if ((parameter.Direction == ParameterDirection.InputOutput || parameter.Direction == ParameterDirection.Input) && (parameter.Value == null)) { parameter.Value = DBNull.Value; } } command.Parameters.AddRange(parms); } } #region ExecuteNonQuery /// <summary> /// 執行SQL語句,返回影響的行數 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回影響的行數</returns> public static int ExecuteNonQuery(string connectionString, string commandText, params SqlParameter[] parms) { using (SqlConnection connection = new SqlConnection(connectionString)) { return ExecuteNonQuery(connection, CommandType.Text, commandText, parms); } } /// <summary> /// 執行SQL語句,返回影響的行數 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回影響的行數</returns> public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText, params SqlParameter[] parms) { using (SqlConnection connection = new SqlConnection(connectionString)) { return ExecuteNonQuery(connection, commandType, commandText, parms); } } /// <summary> /// 執行SQL語句,返回影響的行數 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回影響的行數</returns> public static int ExecuteNonQuery(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteNonQuery(connection, null, commandType, commandText, parms); } /// <summary> /// 執行SQL語句,返回影響的行數 /// </summary> /// <param name="transaction">事務</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回影響的行數</returns> public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteNonQuery(transaction.Connection, transaction, commandType, commandText, parms); } /// <summary> /// 執行SQL語句,返回影響的行數 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="transaction">事務</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回影響的行數</returns> private static int ExecuteNonQuery(SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] parms) { SqlCommand command = new SqlCommand(); PrepareCommand(command, connection, transaction, commandType, commandText, parms); int retval = command.ExecuteNonQuery(); command.Parameters.Clear(); return retval; } #endregion ExecuteNonQuery #region ExecuteScalar /// <summary> /// 執行SQL語句,返回結果集中的第一行第一列 /// </summary> /// <typeparam name="T">返回對象類型</typeparam> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一行第一列</returns> public static T ExecuteScalar<T>(string connectionString, string commandText, params SqlParameter[] parms) { object result = ExecuteScalar(connectionString, commandText, parms); if (result != null) { return (T)Convert.ChangeType(result, typeof(T)); ; } return default(T); } /// <summary> /// 執行SQL語句,返回結果集中的第一行第一列 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一行第一列</returns> public static object ExecuteScalar(string connectionString, string commandText, params SqlParameter[] parms) { using (SqlConnection connection = new SqlConnection(connectionString)) { return ExecuteScalar(connection, CommandType.Text, commandText, parms); } } /// <summary> /// 執行SQL語句,返回結果集中的第一行第一列 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一行第一列</returns> public static object ExecuteScalar(string connectionString, CommandType commandType, string commandText, params SqlParameter[] parms) { using (SqlConnection connection = new SqlConnection(connectionString)) { return ExecuteScalar(connection, commandType, commandText, parms); } } /// <summary> /// 執行SQL語句,返回結果集中的第一行第一列 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一行第一列</returns> public static object ExecuteScalar(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteScalar(connection, null, commandType, commandText, parms); } /// <summary> /// 執行SQL語句,返回結果集中的第一行第一列 /// </summary> /// <param name="transaction">事務</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一行第一列</returns> public static object ExecuteScalar(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteScalar(transaction.Connection, transaction, commandType, commandText, parms); } /// <summary> /// 執行SQL語句,返回結果集中的第一行第一列 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="transaction">事務</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一行第一列</returns> private static object ExecuteScalar(SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] parms) { SqlCommand command = new SqlCommand(); PrepareCommand(command, connection, transaction, commandType, commandText, parms); object retval = command.ExecuteScalar(); command.Parameters.Clear(); return retval; } #endregion ExecuteScalar #region ExecuteDataReader /// <summary> /// 執行SQL語句,返回只讀數據集 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回只讀數據集</returns> private static SqlDataReader ExecuteDataReader(string connectionString, string commandText, params SqlParameter[] parms) { SqlConnection connection = new SqlConnection(connectionString); return ExecuteDataReader(connection, null, CommandType.Text, commandText, parms); } /// <summary> /// 執行SQL語句,返回只讀數據集 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回只讀數據集</returns> private static SqlDataReader ExecuteDataReader(string connectionString, CommandType commandType, string commandText, params SqlParameter[] parms) { SqlConnection connection = new SqlConnection(connectionString); return ExecuteDataReader(connection, null, commandType, commandText, parms); } /// <summary> /// 執行SQL語句,返回只讀數據集 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回只讀數據集</returns> private static SqlDataReader ExecuteDataReader(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteDataReader(connection, null, commandType, commandText, parms); } /// <summary> /// 執行SQL語句,返回只讀數據集 /// </summary> /// <param name="transaction">事務</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回只讀數據集</returns> private static SqlDataReader ExecuteDataReader(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteDataReader(transaction.Connection, transaction, commandType, commandText, parms); } /// <summary> /// 執行SQL語句,返回只讀數據集 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="transaction">事務</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回只讀數據集</returns> private static SqlDataReader ExecuteDataReader(SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] parms) { SqlCommand command = new SqlCommand(); PrepareCommand(command, connection, transaction, commandType, commandText, parms); return command.ExecuteReader(CommandBehavior.CloseConnection); } #endregion #region ExecuteDataRow /// <summary> /// 執行SQL語句,返回結果集中的第一行 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>,返回結果集中的第一行</returns> public static DataRow ExecuteDataRow(string connectionString, string commandText, params SqlParameter[] parms) { DataTable dt = ExecuteDataTable(connectionString, CommandType.Text, commandText, parms); return dt.Rows.Count > 0 ? dt.Rows[0] : null; } /// <summary> /// 執行SQL語句,返回結果集中的第一行 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>,返回結果集中的第一行</returns> public static DataRow ExecuteDataRow(string connectionString, CommandType commandType, string commandText, params SqlParameter[] parms) { DataTable dt = ExecuteDataTable(connectionString, commandType, commandText, parms); return dt.Rows.Count > 0 ? dt.Rows[0] : null; } /// <summary> /// 執行SQL語句,返回結果集中的第一行 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>,返回結果集中的第一行</returns> public static DataRow ExecuteDataRow(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] parms) { DataTable dt = ExecuteDataTable(connection, commandType, commandText, parms); return dt.Rows.Count > 0 ? dt.Rows[0] : null; } /// <summary> /// 執行SQL語句,返回結果集中的第一行 /// </summary> /// <param name="transaction">事務</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>,返回結果集中的第一行</returns> public static DataRow ExecuteDataRow(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] parms) { DataTable dt = ExecuteDataTable(transaction, commandType, commandText, parms); return dt.Rows.Count > 0 ? dt.Rows[0] : null; } #endregion ExecuteDataRow #region ExecuteDataTable /// <summary> /// 執行SQL語句,返回結果集中的第一個數據表 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一個數據表</returns> public static DataTable ExecuteDataTable(string connectionString, string commandText, params SqlParameter[] parms) { return ExecuteDataSet(connectionString, CommandType.Text, commandText, parms).Tables[0]; } /// <summary> /// 執行SQL語句,返回結果集中的第一個數據表 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一個數據表</returns> public static DataTable ExecuteDataTable(string connectionString, CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteDataSet(connectionString, commandType, commandText, parms).Tables[0]; } /// <summary> /// 執行SQL語句,返回結果集中的第一個數據表 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一個數據表</returns> public static DataTable ExecuteDataTable(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteDataSet(connection, commandType, commandText, parms).Tables[0]; } /// <summary> /// 執行SQL語句,返回結果集中的第一個數據表 /// </summary> /// <param name="transaction">事務</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集中的第一個數據表</returns> public static DataTable ExecuteDataTable(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteDataSet(transaction, commandType, commandText, parms).Tables[0]; } /// <summary> /// 獲取空表結構 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="tableName">數據表名稱</param> /// <returns>返回結果集中的第一個數據表</returns> public static DataTable ExecuteEmptyDataTable(string connectionString, string tableName) { return ExecuteDataSet(connectionString, CommandType.Text, string.Format("select * from {0} where 1=-1", tableName)).Tables[0]; } /// <summary> /// 執行SQL語句,返回結果集中的第一個數據表 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="sql">SQL語句</param> /// <param name="order">排序SQL,如"ORDER BY ID DESC"</param> /// <param name="pageSize">每頁記錄數</param> /// <param name="pageIndex">頁索引</param> /// <param name="parms">查詢參數</param> /// <param name="query">查詢SQL</param> /// <param name="cte">CTE表達式</param> /// <returns></returns> public static DataTable ExecutePageDataTable(string connectionString, string sql, string order, int pageSize, int pageIndex, SqlParameter[] parms = null, string query = null, string cte = null) { string psql = string.Format(@" {3} SELECT * FROM ( SELECT ROW_NUMBER() OVER (ORDER BY {1}) RowNumber,* FROM ( {0} ) t WHERE 1 = 1 {2} ) t WHERE RowNumber BETWEEN @RowNumber_Begin AND @RowNumber_End", sql, order, query, cte); List<SqlParameter> paramlist = new List<SqlParameter>() { new SqlParameter("@RowNumber_Begin", SqlDbType.Int){ Value = (pageIndex - 1) * pageSize + 1 }, new SqlParameter("@RowNumber_End", SqlDbType.Int){ Value = pageIndex * pageSize } }; if (parms != null) paramlist.AddRange(parms); return ExecuteDataTable(connectionString, psql, paramlist.ToArray()); } #endregion ExecuteDataTable #region ExecuteDataSet /// <summary> /// 執行查詢語句,返回DataSet /// </summary> /// <param name="SQLString">查詢語句</param> /// <returns>DataSet</returns> public static DataSet ExecuteDataSet(string SQLString, string connectionString) { using (SqlConnection connection = new SqlConnection(connectionString)) { DataSet ds = new DataSet(); try { connection.Open(); SqlDataAdapter command = new SqlDataAdapter(SQLString, connection); command.Fill(ds, "ds"); } catch (System.Data.SqlClient.SqlException ex) { throw new Exception(ex.Message); } return ds; } } /// <summary> /// 執行SQL語句,返回結果集 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="commandText">SQL語句</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集</returns> public static DataSet ExecuteDataSet(string connectionString, string commandText, params SqlParameter[] parms) { return ExecuteDataSet(connectionString, CommandType.Text, commandText, parms); } /// <summary> /// 執行SQL語句,返回結果集 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集</returns> public static DataSet ExecuteDataSet(string connectionString, CommandType commandType, string commandText, params SqlParameter[] parms) { using (SqlConnection connection = new SqlConnection(connectionString)) { return ExecuteDataSet(connection, commandType, commandText, parms); } } /// <summary> /// 執行SQL語句,返回結果集 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集</returns> public static DataSet ExecuteDataSet(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteDataSet(connection, null, commandType, commandText, parms); } /// <summary> /// 執行SQL語句,返回結果集 /// </summary> /// <param name="transaction">事務</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集</returns> public static DataSet ExecuteDataSet(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] parms) { return ExecuteDataSet(transaction.Connection, transaction, commandType, commandText, parms); } /// <summary> /// 執行SQL語句,返回結果集 /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="transaction">事務</param> /// <param name="commandType">命令類型(存儲過程,命令文本, 其它.)</param> /// <param name="commandText">SQL語句或存儲過程名稱</param> /// <param name="parms">查詢參數</param> /// <returns>返回結果集</returns> private static DataSet ExecuteDataSet(SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] parms) { SqlCommand command = new SqlCommand(); PrepareCommand(command, connection, transaction, commandType, commandText, parms); SqlDataAdapter adapter = new SqlDataAdapter(command); DataSet ds = new DataSet(); adapter.Fill(ds); if (commandText.IndexOf("@") > 0) { commandText = commandText.ToLower(); int index = commandText.IndexOf("where "); if (index < 0) { index = commandText.IndexOf("\nwhere"); } if (index > 0) { ds.ExtendedProperties.Add("SQL", commandText.Substring(0, index - 1)); //將獲取的語句保存在表的一個附屬數組里,方便更新時生成CommandBuilder } else { ds.ExtendedProperties.Add("SQL", commandText); //將獲取的語句保存在表的一個附屬數組里,方便更新時生成CommandBuilder } } else { ds.ExtendedProperties.Add("SQL", commandText); //將獲取的語句保存在表的一個附屬數組里,方便更新時生成CommandBuilder } foreach (DataTable dt in ds.Tables) { dt.ExtendedProperties.Add("SQL", ds.ExtendedProperties["SQL"]); } command.Parameters.Clear(); return ds; } #endregion ExecuteDataSet #region 批量操作 /// <summary> /// 大批量數據插入 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="table">數據表</param> public static void BulkInsert(string connectionString, DataTable table) { if (string.IsNullOrEmpty(table.TableName)) throw new Exception("DataTable.TableName屬性不能為空"); using (SqlBulkCopy bulk = new SqlBulkCopy(connectionString)) { bulk.BatchSize = BatchSize; bulk.BulkCopyTimeout = CommandTimeOut; bulk.DestinationTableName = table.TableName; foreach (DataColumn col in table.Columns) { bulk.ColumnMappings.Add(col.ColumnName, col.ColumnName); } bulk.WriteToServer(table); bulk.Close(); } } /// <summary> /// 使用MySqlDataAdapter批量更新數據 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="table">數據表</param> public static void BatchUpdate(string connectionString, DataTable table) { SqlConnection connection = new SqlConnection(connectionString); SqlCommand command = connection.CreateCommand(); command.CommandTimeout = CommandTimeOut; command.CommandType = CommandType.Text; SqlDataAdapter adapter = new SqlDataAdapter(command); SqlCommandBuilder commandBulider = new SqlCommandBuilder(adapter); commandBulider.ConflictOption = ConflictOption.OverwriteChanges; SqlTransaction transaction = null; try { connection.Open(); transaction = connection.BeginTransaction(); //設置批量更新的每次處理條數 adapter.UpdateBatchSize = BatchSize; //設置事物 adapter.SelectCommand.Transaction = transaction; if (table.ExtendedProperties["SQL"] != null) { adapter.SelectCommand.CommandText = table.ExtendedProperties["SQL"].ToString(); } adapter.Update(table); transaction.Commit();/////提交事務 } catch (SqlException ex) { if (transaction != null) transaction.Rollback(); throw ex; } finally { connection.Close(); connection.Dispose(); } } /// <summary> /// 分批次批量刪除數據 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="sql">SQL語句</param> /// <param name="batchSize">每批次更新記錄行數</param> /// <param name="interval">批次執行間隔(秒)</param> public static void BatchDelete(string connectionString, string sql, int batchSize = 1000, int interval = 1) { sql = sql.ToLower(); if (batchSize < 1000) batchSize = 1000; if (interval < 1) interval = 1; while (ExecuteScalar(connectionString, sql.Replace("delete", "select top 1 1")) != null) { ExecuteNonQuery(connectionString, CommandType.Text, sql.Replace("delete", string.Format("delete top ({0})", batchSize))); System.Threading.Thread.Sleep(interval * 1000); } } /// <summary> /// 分批次批量更新數據 /// </summary> /// <param name="connectionString">數據庫連接字符串</param> /// <param name="sql">SQL語句</param> /// <param name="batchSize">每批次更新記錄行數</param> /// <param name="interval">批次執行間隔(秒)</param> public static void BatchUpdate(string connectionString, string sql, int batchSize = 1000, int interval = 1) { if (batchSize < 1000) batchSize = 1000; if (interval < 1) interval = 1; string existsSql = Regex.Replace(sql, @"[\w\s.=,']*from", "select top 1 1 from", RegexOptions.IgnoreCase); existsSql = Regex.Replace(existsSql, @"set[\w\s.=,']* where", "where", RegexOptions.IgnoreCase); existsSql = Regex.Replace(existsSql, @"update", "select top 1 1 from", RegexOptions.IgnoreCase); while (ExecuteScalar<int>(connectionString, existsSql) != 0) { ExecuteNonQuery(connectionString, CommandType.Text, Regex.Replace(sql, "update", string.Format("update top ({0})", batchSize), RegexOptions.IgnoreCase)); System.Threading.Thread.Sleep(interval * 1000); } } #endregion 批量操作 #endregion 靜態方法 }
最后 在原項目數據庫需要新建三張數據表:分別記錄公眾號信息、access_token信息以及分享信息(dt_weixin_access_token、dt_weixin_account、dt_weixin_jsapiticket)
數據表結構如下:

USE [數據庫名稱] GO /****** Object: Table [dbo].[dt_weixin_access_token] Script Date: 2018-04-07 10:49:17 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[dt_weixin_access_token]( [id] [int] IDENTITY(1,1) NOT NULL, [account_id] [int] NULL, [access_token] [nvarchar](1000) NULL, [expires_in] [int] NULL CONSTRAINT [DF__dt_weixin__expir__233F2673] DEFAULT ((0)), [count] [int] NULL CONSTRAINT [DF__dt_weixin__count__24334AAC] DEFAULT ((0)), [add_time] [datetime] NULL CONSTRAINT [DF__dt_weixin__add_t__25276EE5] DEFAULT (getdate()), CONSTRAINT [PK_DT_WEIXIN_ACCESS_TOKEN] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO /****** Object: Table [dbo].[dt_weixin_account] Script Date: 2018-04-07 10:49:17 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[dt_weixin_account]( [id] [int] IDENTITY(1,1) NOT NULL, [name] [nvarchar](100) NULL, [originalid] [nvarchar](50) NULL, [wxcode] [nvarchar](50) NULL, [token] [nvarchar](300) NULL, [appid] [nvarchar](100) NULL, [appsecret] [nvarchar](150) NULL, [is_push] [tinyint] NULL CONSTRAINT [DF__dt_weixin__is_pu__19B5BC39] DEFAULT ((0)), [sort_id] [int] NULL CONSTRAINT [DF__dt_weixin__sort___1AA9E072] DEFAULT ((99)), [add_time] [datetime] NULL CONSTRAINT [DF__dt_weixin__add_t__1B9E04AB] DEFAULT (getdate()), CONSTRAINT [PK_DT_WEIXIN_ACCOUNT] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO /****** Object: Table [dbo].[dt_weixin_jsapiticket] Script Date: 2018-04-07 10:49:17 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[dt_weixin_jsapiticket]( [id] [int] NOT NULL, [jsapi_ticket] [varchar](500) NULL, [ticket_expires] [varchar](500) NULL, [add_time] [datetime] NULL CONSTRAINT [DF_dt_weixin_jsapiticket_add_time] DEFAULT (getdate()), CONSTRAINT [PK_dt_weixin_jsapiticket] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO SET IDENTITY_INSERT [dbo].[dt_weixin_access_token] ON GO INSERT [dbo].[dt_weixin_access_token] ([id], [account_id], [access_token], [expires_in], [count], [add_time]) VALUES (1, 1, N'8_NX5IydeBm6ZEnUAzyXNKDIVJEJy-hzTbTaXd7w-q51P96XDcmFP2OYnJRyJ7rBAt9peJ-C5ad8RPkIDe8Vsm_LCdmOvyrVfWuotnTpCngXZFUVdbgCqOH03LBmWGMg69HRCp5ActsK2o269hUQJaAHAHDW', 1200, 1, CAST(N'2018-04-06 22:23:14.870' AS DateTime)) GO SET IDENTITY_INSERT [dbo].[dt_weixin_access_token] OFF GO SET IDENTITY_INSERT [dbo].[dt_weixin_account] ON GO INSERT [dbo].[dt_weixin_account] ([id], [name], [originalid], [wxcode], [token], [appid], [appsecret], [is_push], [sort_id], [add_time]) VALUES (1, N'WBC', N'gh_f43eded4a607', N'szsanfang', NULL, N'AppId', N'appSecret', 0, 99, CAST(N'2018-04-03 14:51:19.310' AS DateTime)) GO SET IDENTITY_INSERT [dbo].[dt_weixin_account] OFF GO INSERT [dbo].[dt_weixin_jsapiticket] ([id], [jsapi_ticket], [ticket_expires], [add_time]) VALUES (1, N'kgt8ON7yVITDhtdwci0qea8xYacVzuqZEqxNGwp-1WE0DTSI2wkMf1-e__jGosg516Xz2u9M-xsbXOd4eZBcMw', N'1523025795', CAST(N'2018-04-06 22:23:15.000' AS DateTime)) GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'自增ID' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_access_token', @level2type=N'COLUMN',@level2name=N'id' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'公眾賬戶ID' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_access_token', @level2type=N'COLUMN',@level2name=N'account_id' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'access_token值' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_access_token', @level2type=N'COLUMN',@level2name=N'access_token' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'有效期(秒)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_access_token', @level2type=N'COLUMN',@level2name=N'expires_in' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'總數' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_access_token', @level2type=N'COLUMN',@level2name=N'count' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'創建時間' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_access_token', @level2type=N'COLUMN',@level2name=N'add_time' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'公眾平台access_token存儲' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_access_token' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'自增ID' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_account', @level2type=N'COLUMN',@level2name=N'id' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'公眾號名稱' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_account', @level2type=N'COLUMN',@level2name=N'name' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'公眾號原始ID' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_account', @level2type=N'COLUMN',@level2name=N'originalid' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'微信號' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_account', @level2type=N'COLUMN',@level2name=N'wxcode' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'令牌必須與微信平台對應' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_account', @level2type=N'COLUMN',@level2name=N'token' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'appid(僅用於高級接口)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_account', @level2type=N'COLUMN',@level2name=N'appid' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'appsecret(僅用於高級接口)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_account', @level2type=N'COLUMN',@level2name=N'appsecret' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否支持網站內容推送' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_account', @level2type=N'COLUMN',@level2name=N'is_push' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'排序號' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_account', @level2type=N'COLUMN',@level2name=N'sort_id' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'添加時間' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_account', @level2type=N'COLUMN',@level2name=N'add_time' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'微信公眾平台賬戶' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'dt_weixin_account' GO
本地寫完代碼 可以放到綁定過域名的 服務器 進行日志打印調試,看看各項數據是否正常拿到。
最后實現轉發 效果如下: