利用Topshelf搭建Windowns服務實現定期自動新增資料邏輯和原理
阿新 • • 發佈:2019-02-14
一、Topshelf基本配置
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Topshelf; namespace MealTimer { public class Program { public static void Main() { HostFactory.Run(x => //這裡通過HostFactory.Run安裝這個host,通過其lambda表示式的x來進行各種host級別的引數配置。 { x.Service<MealTimer>(s => //這裡我們告訴Topshelf這裡有一個‘TownCrier’服務,lambda表示式的s用於設定各種服務級別的配置。 { s.ConstructUsing(name => new MealTimer()); //這裡告訴Topshelf如何給這個服務構建一個例項,這裡我們只是簡單的將例項new出來,實際使用中通常會通過IoC來注入一個例項,程式碼類似‘container.GetInstance<TownCrier>()’. s.WhenStarted(tc => tc.Start()); //告訴Topshelf啟動這個服務時做什麼。 s.WhenStopped(tc => tc.Stop()); //告訴Topshelf如何停止這個服務時做什麼。 }); //以本地帳戶身份執行,這裡選擇的是登入為:本地系統local system x.RunAsLocalSystem(); x.SetDescription("內部系統自動新增報餐表"); //設定該服務的描述 x.SetDisplayName("CanYouAddmealService"); //設定該服務的顯示名稱。 x.SetServiceName("CanYouAddmealService"); //設定該服務自身的名字,即服務名稱。 //服務啟動模式 x.StartAutomatically(); //自動 x.EnableServiceRecovery(rc => rc.RestartService(1));// 服務如果意外停止,1分鐘後恢復啟動 }); } } }
二、配置Start方法
public void Start() { Thread sendThread = new Thread(new ThreadStart(delegate() { try { while (true) { if (IsDBOnline()) { AddMealSet(); } else { Thread.Sleep(60 * 60 * 1000); SaveRecord("\r\n" + "資料庫連結失敗,執行緒休眠【" + 60 + "】分鐘。"); } } } catch (Exception ex) { SaveRecord("\r\n" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n" + ex); //執行緒終止,只能在該執行緒的內部終止,不能寫線上程類的外部 Thread.CurrentThread.Abort(); } })); //啟動執行緒 sendThread.Start(); //指定後臺執行緒 sendThread.IsBackground = true; }
在Start方法裡面,定義一個while(true)的死迴圈,死迴圈裡面執行一次新增方法,就定時休眠,在執行新增方法前,先檢測一下資料庫連線狀態,如果暫時連線失敗,等60分鐘後再啟動服務。
/// <summary> /// 資料庫是否線上 /// </summary> /// <returns></returns> public bool IsDBOnline() { string connString = ConfigurationSettings.AppSettings["MsSql"]; SqlConnection Connection = new SqlConnection(connString); try { Connection.Open(); } catch (Exception ex) { SaveRecord("\r\n" + "資料庫連結錯誤:" + ex.ToString()); return false; } finally { Connection.Close(); } return true; }
三、定時新增資料方法
/// <summary>
/// 根據當前時間和系統設定時間對比,進行自動報餐處理
/// </summary>
public void AddMealSet()
{
while (true)//構建一個死迴圈,裡面只有執行緒休眠時間,到了時間重新判斷,無限迴圈執行
{
#region 引數配置
//取出配置檔案的定時新增報餐資料
string AddTime = ConfigurationSettings.AppSettings["AddTime"];
//取出配置檔案的星期值
string dayofweek = ConfigurationSettings.AppSettings["Day"];
//取出配置裡面的資料要放在while (true)迴圈裡面,放在外面,如果更新了配置檔案,這些資料不能被讀取到,只能重新啟動才能讀取到最新
DateTime Day = DateTime.Now;//DateTime.Now要放在while (true)迴圈裡面,否則DateTime.Now永遠是第一次啟動時的時間,沒有更新
string MealAutoAddstring = MealAutoAdd.AddMeal(Day);// 根據時間判斷自動插入資料庫一條報餐表資料語句,返回語句
if (string.IsNullOrEmpty(AddTime))
{
throw new Exception("從App.config檔案獲取定時傳送簡訊時間AddTime報錯,執行緒已經退出,請排查錯誤後,重啟伺服器。");
}
if (string.IsNullOrEmpty(MealAutoAddstring))
{
throw new Exception("報餐表資料語句,返回值為空!");
}
int HHNow = Convert.ToInt32(Day.ToString("HH"));//定義現在時間小時數
int mmNow = Convert.ToInt32(Day.ToString("mm"));//定義現在時間分鐘數
int AddTime_Val = Convert.ToInt32(AddTime);//獲取新增報餐時間小時數
int _SleepTime = 0;
string monthfirstday = DateTime.Now.Date.ToString("dd");//獲取每月1號
#endregion
if (MealAutoAdd.Week(Day.DayOfWeek.ToString()) != dayofweek & MealAutoAdd.Week(Day.DayOfWeek.ToString()) != "星期二")//非週二、三時間,執行緒休眠24小時.
{
#region 非週二、三時間,執行緒休眠24小時
_SleepTime = 86400000;
if (monthfirstday == "01")
{
AddHumanCost();//每月1號,自動新增人力成本資料
}
SaveRecord("\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n" +
MealAutoAdd.Week(Day.DayOfWeek.ToString()) + ",執行緒休眠:" + 24 + "小時,共(毫秒):" + _SleepTime);
Thread.Sleep(_SleepTime);
#endregion
}
else if (MealAutoAdd.Week(Day.DayOfWeek.ToString()) == "星期二")//為了避免在週二重啟伺服器或服務重啟,如果休眠24小時,可能會錯過週三的報餐時間
{
#region 星期二,如果當前小時數小於0,則休眠時間可以是24小時,休眠結束之後,還在定時報餐時間範圍內
if (HHNow - AddTime_Val < 0)//如果當前小時數小於0,則休眠時間可以是24小時,休眠結束之後,還在定時報餐時間範圍內
{
if (monthfirstday == "01")
{
AddHumanCost();//每月1號,自動新增人力成本資料
}
_SleepTime = ((24 + AddTime_Val - HHNow - 1) * 60000 * 60) + (60 - mmNow) * 60000;//當前時間 如果是7:45,休眠24小時之後,還是7:45,所以要加上15分鐘,正好8點
string SaveRecordstring = mmNow == 0
? "\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") +
"\r\n週二時間,當前時間在定時報餐之前,執行緒休眠:" +
(24 + AddTime_Val - HHNow) + "小時,共(毫秒):" + _SleepTime
: "\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") +
"\r\n週二時間,當前時間在定時報餐之前,執行緒休眠:" +
(24 + AddTime_Val - HHNow - 1) + "小時" + (60 - mmNow) +
"分鐘,共(毫秒):" + _SleepTime;
SaveRecord(SaveRecordstring);
Thread.Sleep(_SleepTime);
}
#endregion
#region 如果當前小時數大於0,則休眠時間不能是24小時,否則會造成休眠結束之後,錯過報餐時間
else if (HHNow - AddTime_Val > 0)//如果當前小時數大於0,則休眠時間不能是24小時,否則會造成休眠結束之後,錯過報餐時間
{
if (monthfirstday == "01")
{
AddHumanCost();//每月1號,自動新增人力成本資料
}
_SleepTime = (24 - HHNow - 1) * 60000 * 60 + (60 - mmNow) * 60000;//當前時間 如果是9:45,需要休眠14:15小時之後,為整點
string SaveRecordstring = mmNow == 0
? "\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") +
"\r\n週二時間,當前時間在定時報餐之後" + (HHNow - AddTime_Val) + "小時,執行緒休眠:" +
(24 - HHNow) + "小時,共(毫秒):" +
_SleepTime
: "\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") +
"\r\n週二時間,當前時間在定時報餐之後" + (HHNow - AddTime_Val) + "小時,執行緒休眠:" +
(24 - HHNow - 1) + "小時" + (60 - mmNow) + "分鐘,共(毫秒):" +
_SleepTime;
SaveRecord(SaveRecordstring);
Thread.Sleep(_SleepTime);
}
#endregion
#region 時間在當前時段,如果當前時間是整點數
else//時間在當前時段,如果當前時間是整點數
{
_SleepTime = 23 * 3600000 + (60 - mmNow) * 60000;//當前時間 如果是8:45,需要休眠23:15小時之後,為整點
if (monthfirstday == "01")
{
AddHumanCost();//每月1號,自動新增人力成本資料
}
string SaveRecordstring = mmNow == 0
? "\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") +
"\r\n週二時間,當前時間在定時報餐之後" + (HHNow - AddTime_Val) + "小時,執行緒休眠:" + 24 +
"小時,共(毫秒):" + _SleepTime
: "\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") +
"\r\n週二時間,當前時間在定時報餐之後" + (HHNow - AddTime_Val) + "小時,執行緒休眠:" + 23 +
"小時" + (60 - mmNow) + "分鐘,共(毫秒):" + _SleepTime;
SaveRecord(SaveRecordstring);
Thread.Sleep(_SleepTime);
}
#endregion
}
else//當前時間為週三時間
{
#region 當前時間為週三時間,也就是報餐時間
if (DateTime.Now.ToString("HH") == AddTime & MealAutoAdd.Week(Day.DayOfWeek.ToString()) == dayofweek)//判斷是否到小時點,和對應的星期幾
{
//關鍵一步:不管伺服器是否重新啟動,都要判斷資料是否已經新增過
string Holiday = MealAutoAdd.MealDay_1(Day);
if (Holiday == "" & !isAddMealSet())//先判斷是不是已經新增了節假日的報餐資料,再判斷是否新增週末報餐的資料
{
SqlHelper.GetSingle(MealAutoAddstring);
SqlHelper.GetSingle(
"INSERT INTO sys_Event (E_U_LoginName, E_DateTime,E_Record) VALUES ('報餐定時器', '" +
Day.ToString("yyyy-MM-dd HH:mm:ss") + "', '自動新增“" +
SqlHelper.GetSingle("SELECT TOP 1 MS_MealType FROM sys_MealSet order by MS_ID DESC") +
"”報餐資料')");
SaveRecord("\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n自動新增“" +
SqlHelper.GetSingle(
"SELECT TOP 1 MS_MealType FROM sys_MealSet order by MS_ID DESC") + "”報餐資料'");//記錄到本地日誌
AddMeal();//根據自動報餐設定,自動新增報餐記錄
}
if (Holiday != "" & !isHolidayAdd())//先判斷是不是已經新增了節假日的報餐資料,再判斷是否新增週末報餐的資料
{
SqlHelper.GetSingle(MealAutoAddstring);
SqlHelper.GetSingle(
"INSERT INTO sys_Event (E_U_LoginName, E_DateTime,E_Record) VALUES ('報餐定時器', '" +
Day.ToString("yyyy-MM-dd HH:mm:ss") + "', '自動新增“" +
SqlHelper.GetSingle("SELECT TOP 1 MS_MealType FROM sys_MealSet order by MS_ID DESC") +
"”報餐資料')");
SaveRecord("\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n自動新增“" +
SqlHelper.GetSingle(
"SELECT TOP 1 MS_MealType FROM sys_MealSet order by MS_ID DESC") + "”報餐資料'");
}
else//這個else裡面一定要進行休眠,否則在這一個小時之內無數次迴圈新增報餐資料
{
if (monthfirstday == "01")
{
AddHumanCost();//每月1號,自動新增人力成本資料
}
SaveRecord("\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n在自動報餐時間範圍內,已經進行報餐資料新增,執行緒休眠(分鐘):" + (60 - mmNow));
//注意此處不能終止迴圈,否則跳出迴圈,不能再次新增資料
Thread.Sleep((60 - mmNow) * 60000);
}
}
#endregion
#region 如果不是在報餐的正點數
else//如果不是在報餐的正點數
{
if (HHNow < AddTime_Val & MealAutoAdd.Week(Day.DayOfWeek.ToString()) == dayofweek)//判斷小時點,和對應的星期幾
{
_SleepTime = (AddTime_Val - HHNow - 1) * 60000 * 60 + (60 - mmNow) * 60000;//假如現在是7:45,,8點為報餐整點,則休眠15分鐘即可
string SaveRecordstring = mmNow == 0
? "\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") +
"\r\n不在自動報餐時間範圍內,執行緒休眠:" + (AddTime_Val - HHNow) + "小時,共(毫秒):" + _SleepTime
: "\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") +
"\r\n不在自動報餐時間範圍內,執行緒休眠:" + (AddTime_Val - HHNow - 1) + "小時" +
(60 - mmNow) + "分鐘,共(毫秒):" + _SleepTime;
SaveRecord(SaveRecordstring);
if (monthfirstday == "01")
{
AddHumanCost();//每月1號,自動新增人力成本資料
}
Thread.Sleep(_SleepTime);//當天時間,時間小時數小於報餐小時數,休眠當前時間小時數和報餐時間點數的差值,例如:當前時間是7點,則休眠1個小時
}
if (HHNow > AddTime_Val & MealAutoAdd.Week(Day.DayOfWeek.ToString()) == dayofweek)//判斷是否到小時點,和對應的星期幾
{
_SleepTime = (24 - HHNow - 1) * 60000 * 60 + (60 - mmNow) * 60000;//假如現在是9:45,則休眠14:15分鐘,可到24整點
string SaveRecordstring = mmNow == 0
? "\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") +
"\r\n不在自動報餐時間範圍內,執行緒休眠:" + (24 - HHNow) + "小時,共(毫秒):" + _SleepTime
: "\r\n" + Day.ToString("yyyy-MM-dd HH:mm:ss") +
"\r\n不在自動報餐時間範圍內,執行緒休眠:" + (24 - HHNow - 1) + "小時" +
(60 - mmNow) + "分鐘,共(毫秒):" + _SleepTime;
SaveRecord(SaveRecordstring);//當天時間,時間小時數大於報餐小時數,休眠當天的剩餘小時數,例如:當前時間是9點,則休眠24-9=15個小時
if (monthfirstday == "01")
{
AddHumanCost();//每月1號,自動新增人力成本資料
}
Thread.Sleep(_SleepTime);
}
}
#endregion
}
}
}
四、自動新增報餐方法
/// <summary>
/// 新增報餐方法
/// </summary>
public void AddMeal()
{
DataTable dt = SqlHelper.QueryTable("SELECT * FROM sys_MealDefaultValues");
string MealName = ConfigurationSettings.AppSettings["MealName"];
string Password = ConfigurationSettings.AppSettings["Password"];
string host = ConfigurationSettings.AppSettings["host"];
for (int i = 0; i < dt.Rows.Count; i++)
{
int MS_ID = Convert.ToInt32(SqlHelper.GetSingle("SELECT TOP 1 MS_ID FROM sys_MealSet order by MS_ID DESC").ToString());
if (dt.Rows[i][1].ToString() == "0")//dt.Rows[i][1].ToString()
{
string M_UserID = dt.Rows[i][2].ToString();
string M_day_1_Lunch = dt.Rows[i][3].ToString();
string M_day_1_Dinner = dt.Rows[i][4].ToString();
string M_day_2_Lunch = dt.Rows[i][5].ToString();
string M_day_2_Dinner = dt.Rows[i][6].ToString();
string M_IsMail = dt.Rows[i][7].ToString();
string AddString =
"INSERT INTO sys_Meal (M_UserID, M_MS_ID,M_day_1_Lunch,M_day_1_Dinner,M_day_2_Lunch,M_day_2_Dinner) VALUES ('" +
M_UserID + "','" + MS_ID + "','" + M_day_1_Lunch + "','" + M_day_1_Dinner + "','" +
M_day_2_Lunch + "','" + M_day_2_Dinner + "')";
int info = SqlHelper.ExecuteSql(AddString);
#region 設定MealTo,Content
string MealTo =
SqlHelper.GetSingle("SELECT U_CompanyMail FROM sys_User where UserID='" + dt.Rows[i][2] + "'").ToString() !=
""
? SqlHelper.GetSingle("SELECT U_CompanyMail FROM sys_User where UserID='" + dt.Rows[i][2] + "'").ToString()
: SqlHelper.GetSingle("SELECT U_Email FROM sys_User where UserID='" + dt.Rows[i][2] + "'").ToString();
string Content = "尊敬的:" +
SqlHelper.GetSingle("SELECT U_LoginName FROM sys_User where UserID='" +
dt.Rows[i][2] + "'") + ",您的報餐情況為:" +
DisabilityType_Value.GetSaturdayDate().ToString("yyyy-MM-dd-星期六") + "(上午:" +
dt.Rows[i][3].ToString().Substring(0, 2) + ",下午:" +
dt.Rows[i][4].ToString().Substring(0, 2) + ");" +
DisabilityType_Value.GetSaturdayDate().AddDays(1).ToString("yyyy-MM-dd-星期日") +
"(上午:" + dt.Rows[i][5].ToString().Substring(0, 2) + ",下午:" +
dt.Rows[i][6].ToString().Substring(0, 2) + ")。報餐郵件是否傳送,現已可在系統中進行設定!";
#endregion
if (info != 0)
{
bool SentOrNot = M_IsMail == "1" ? SendEmail(MealTo, MealName, Password, host, Content) : false;
#region 傳送郵件成功,則日誌記錄中顯示“併發送郵件成功”的欄位,否則不顯示這幾個字
if (SentOrNot)//傳送郵件成功,則日誌記錄中顯示“併發送郵件成功”的欄位,否則不顯示這幾個字
{
SqlHelper.GetSingle(
"INSERT INTO sys_Event (E_U_LoginName, E_DateTime,E_Record) VALUES ('報餐定時器', '" +
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "', '自動新增“" +
SqlHelper.GetSingle("SELECT U_LoginName FROM sys_User where UserID='" + dt.Rows[i][2] +
"'") + "," +
SqlHelper.GetSingle("SELECT TOP 1 MS_MealType FROM sys_MealSet order by MS_ID DESC") +
"”的報餐資料,併發送郵件成功!')");
SaveRecord("\r\n" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n自動新增“" +
SqlHelper.GetSingle("SELECT U_LoginName FROM sys_User where UserID='" +
dt.Rows[i][2] + "'") + "," +
SqlHelper.GetSingle(
"SELECT TOP 1 MS_MealType FROM sys_MealSet order by MS_ID DESC") +
"”的報餐資料,併發送郵件成功!')");
}
#endregion
#region 傳送郵件成功,則日誌記錄中顯示“併發送郵件成功”的欄位,否則不顯示這幾個字
else
{
SqlHelper.GetSingle(
"INSERT INTO sys_Event (E_U_LoginName, E_DateTime,E_Record) VALUES ('報餐定時器', '" +
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "', '自動新增“" +
SqlHelper.GetSingle("SELECT U_LoginName FROM sys_User where UserID='" + dt.Rows[i][2] +
"'") + "," +
SqlHelper.GetSingle("SELECT TOP 1 MS_MealType FROM sys_MealSet order by MS_ID DESC") +
"”的報餐資料!')");
SaveRecord("\r\n" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n自動新增“" +
SqlHelper.GetSingle("SELECT U_LoginName FROM sys_User where UserID='" +
dt.Rows[i][2] + "'") + "," +
SqlHelper.GetSingle(
"SELECT TOP 1 MS_MealType FROM sys_MealSet order by MS_ID DESC") +
"”的報餐資料!')");
}
#endregion
}
}
}
}
五、傳送郵件方法
/// <summary>
/// 傳送郵件方法
/// </summary>
/// <param name="MealTo">郵件接收者的帳號</param>
/// <param name="MealUserName">註冊的郵箱</param>
/// <param name="MealPassword">郵箱密碼</param>
/// <param name="Host">郵箱對應的SMTP伺服器</param>
/// <param name="Content">郵件內容</param>
/// <returns></returns>
public bool SendEmail(string MealTo, string MealUserName, string MealPassword, string Host, string Content)
{
MailMessage msg = new MailMessage();
msg.To.Add(MealTo);//郵件接收者的帳號
msg.From = new MailAddress(MealUserName, "殘友內部系統郵件", System.Text.Encoding.UTF8);//傳送郵件的帳號及顯示名稱和字元編碼
msg.Subject = "殘友內部系統自動增加報餐資料資訊";//郵件標題
msg.SubjectEncoding = System.Text.Encoding.UTF8;//郵件標題編碼
msg.Body = Content;//郵件內容
msg.BodyEncoding = System.Text.Encoding.UTF8;//郵件內容編碼
msg.IsBodyHtml = false;//是否是HTML郵件
msg.Priority = MailPriority.Normal;//郵件優先順序
SmtpClient client = new SmtpClient();
client.Credentials = new System.Net.NetworkCredential(MealUserName, MealPassword);//註冊的郵箱和密碼,就QQ郵箱而言,如果設定了獨立密碼,要用獨立密碼代替密碼
client.Host = Host;//QQ郵箱對應的SMTP伺服器
object userState = msg;
try
{
client.SendAsync(msg, userState);
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
六、SqlHelper類
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Collections;
using System.Data;
using System.Configuration;
using System.Web;
namespace FrameWork
{
public class SqlHelper
{
public static string connectionString = ConfigurationManager.ConnectionStrings["FrameWorkConnectionString"].ConnectionString;
public SqlHelper()
{
}
#region 公用方法
public static int GetMaxID(string FieldName, string TableName)
{
string strsql = "select max(" + FieldName + ")+1 from " + TableName;
object obj = SqlHelper.GetSingle(strsql);
if (obj == null)
{
return 1;
}
else
{
return int.Parse(obj.ToString());
}
}
public static bool Exists(string strSql)
{
object obj = SqlHelper.GetSingle(strSql);
int cmdresult;
if ((Object.Equals(obj, null)) || (Object.Equals(obj, System.DBNull.Value)))
{
cmdresult = 0;
}
else
{
cmdresult = int.Parse(obj.ToString());
}
if (cmdresult == 0)
{
return false;
}
else
{
return true;
}
}
public static bool Exists(string strSql, params SqlParameter[] cmdParms)
{
object obj = SqlHelper.GetSingle(strSql, cmdParms);
int cmdresult;
if ((Object.Equals(obj, null)) || (Object.Equals(obj, System.DBNull.Value)))
{
cmdresult = 0;
}
else
{
cmdresult = int.Parse(obj.ToString());
}
if (cmdresult == 0)
{
return false;
}
else
{
return true;
}
}
#endregion
#region 執行簡單SQL語句
/// <summary>
/// 執行SQL語句,返回影響的記錄數
/// </summary>
/// <param name="SQLString">SQL語句</param>
/// <returns>影響的記錄數</returns>
public static int ExecuteSql(string SQLString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand(SQLString, connection))
{
try
{
connection.Open();
int rows = cmd.ExecuteNonQuery();
return rows;
}
catch (System.Data.SqlClient.SqlException E)
{
connection.Close();
throw new Exception(E.Message);
}
}
}
}
/// <summary>
/// 執行SQL語句,返回影響的記錄數 適用於select語句
/// </summary>
/// <param name="SQLString">SQL語句</param>
/// <returns>影響的記錄數</returns>
public static int ExecuteSql2(string SQLString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand(SQLString, connection))
{
try
{
connection.Open();
int rows = Convert.ToInt32(cmd.ExecuteScalar());
return rows;
}
catch (System.Data.SqlClient.SqlException E)
{
connection.Close();
throw new Exception(E.Message);
}
}
}
}
/// <summary>
/// 執行多條SQL語句,實現資料庫事務。
/// </summary>
/// <param name="SQLStringList">多條SQL語句</param>
public static void ExecuteSqlTran(ArrayList SQLStringList)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
SqlTransaction tx = conn.BeginTransaction();
cmd.Transaction = tx;
try
{
for (int n = 0; n < SQLStringList.Count; n++)
{
string strsql = SQLStringList[n].ToString();
if (strsql.Trim().Length > 1)
{
cmd.CommandText = strsql;
cmd.ExecuteNonQuery();
}
}
tx.Commit();
}
catch (System.Data.SqlClient.SqlException E)
{
tx.Rollback();
throw new Exception(E.Message);
}
}
}
/// <summary>
/// 執行帶一個儲存過程引數的的SQL語句。
/// </summary>
/// <param name="SQLString">SQL語句</param>
/// <param name="content">引數內容,比如一個欄位是格式複雜的文章,有特殊符號,可以通過這個方式新增</param>
/// <returns>影響的記錄數</returns>
public static int ExecuteSql(string SQLString, string content)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(SQLString, connection);
System.Data.SqlClient.SqlParameter myParameter = new System.Data.SqlClient.SqlParameter("@content", SqlDbType.VarChar);
myParameter.Value = content;
cmd.Parameters.Add(myParameter);
try
{
connection.Open();
int rows = cmd.ExecuteNonQuery();
return rows;
}
catch (System.Data.SqlClient.SqlException E)
{
throw new Exception(E.Message);
}
finally
{
cmd.Dispose();
connection.Close();
}
}
}
/// <summary>
/// 向資料庫裡插入影象格式的欄位(和上面情況類似的另一種例項)
/// </summary>
/// <param name="strSQL">SQL語句</param>
/// <param name="fs">影象位元組,資料庫的欄位型別為image的情況</param>
/// <returns>影響的記錄數</returns>
public static int ExecuteSqlInsertImg(string strSQL, byte[] fs)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(strSQL, connection);
System.Data.SqlClient.SqlParameter myParameter = new System.Data.SqlClient.SqlParameter("@fs", SqlDbType.Binary);
myParameter.Value = fs;
cmd.Parameters.Add(myParameter);
try
{
connection.Open();
int rows = cmd.ExecuteNonQuery();
return rows;
}
catch (System.Data.SqlClient.SqlException E)
{
throw new Exception(E.Message);
}
finally
{
cmd.Dispose();
connection.Close();
}
}
}
/// <summary>
/// 執行一條計算查詢結果語句,返回查詢結果(object)。
/// </summary>
/// <param name="SQLString">計算查詢結果語句</param>
/// <returns>查詢結果(object)</returns>
public static object GetSingle(string SQLString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand(SQLString, connection))
{
try
{
connection.Open();
object obj = cmd.ExecuteScalar();
if ((Object.Equals(obj, null)) || (Object.Equals(obj, System.DBNull.Value)))
{
return null;
}
else
{
return obj;
}
}
catch (System.Data.SqlClient.SqlException e)
{
connection.Close();
throw new Exception(e.Message);
}
}
}
}
/// <summary>
/// 執行查詢語句,返回SqlDataReader
/// </summary>
/// <param name="strSQL">查詢語句</param>
/// <returns>SqlDataReader</returns>
public static SqlDataReader ExecuteReader(string strSQL)
{
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(strSQL, connection);
try
{
connection.Open();
SqlDataReader myReader = cmd.ExecuteReader();
return myReader;
}
catch (System.Data.SqlClient.SqlException e)
{
throw new Exception(e.Message);
}
}
/// <summary>
/// 執行查詢語句,返回DataSet
/// </summary>
/// <param name="SQLString">查詢語句</param>
/// <returns>DataSet</returns>
public static DataSet Query(string SQLString)
{
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>
/// 執行查詢語句,返回datatable
/// </summary>
/// <param name="SQLString">查詢語句</param>
/// <returns>DataSet</returns>
public static DataTable QueryTable(string SQLString)
{
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.Tables[0];
}
}
#endregion
#region 執行帶引數的SQL語句
/// <summary>
/// 執行SQL語句,返回影響的記錄數
/// </summary>
/// <param name="SQLString">SQL語句</param>
/// <returns>影響的記錄數</returns>
public static int ExecuteSql(string SQLString, params SqlParameter[] cmdParms)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand())
{
try
{
PrepareCommand(cmd, connection, null, SQLString, cmdParms);
int rows = cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
return rows;
}
catch (System.Data.SqlClient.SqlException E)
{
throw new Exception(E.Message);
}
}
}
}
/// <summary>
/// 執行多條SQL語句,實現資料庫事務。
/// </summary>
/// <param name="SQLStringList">SQL語句的雜湊表(key為sql語句,value是該語句的SqlParameter[])</param>
public static void ExecuteSqlTran(Hashtable SQLStringList)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlTransaction trans = conn.BeginTransaction())
{
SqlCommand cmd = new SqlCommand();
try
{
//迴圈
foreach (DictionaryEntry myDE in SQLStringList)
{
string cmdText = myDE.Key.ToString();
SqlParameter[] cmdParms = (SqlParameter[])myDE.Value;
PrepareCommand(cmd, conn, trans, cmdText, cmdParms);
int val = cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
trans.Commit();
}
}
catch
{
trans.Rollback();
throw;
}
}
}
}
/// <summary>
/// 執行一條計算查詢結果語句,返回查詢結果(object)。
/// </summary>
/// <param name="SQLString">計算查詢結果語句</param>
/// <returns>查詢結果(object)</returns>
public static object GetSingle(string SQLString, 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 new Exception(e.Message);
}
}
}
}
/// <summary>
/// 執行查詢語句,返回SqlDataReader
/// </summary>
/// <param name="strSQL">查詢語句</param>
/// <returns>SqlDataReader</returns>
public static SqlDataReader ExecuteReader(string SQLString, params SqlParameter[] cmdParms)
{
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand();
try
{
PrepareCommand(cmd, connection, null, SQLString, cmdParms);
SqlDataReader myReader = cmd.ExecuteReader();
cmd.Parameters.Clear();
return myReader;
}
catch (System.Data.SqlClient.SqlException e)
{
throw new Exception(e.Message);
}
}
/// <summary>
/// 執行查詢語句,返回DataSet
/// </summary>
/// <param name="SQLString">查詢語句</param>
/// <returns>DataSet</returns>
public static DataSet Query(string SQLString, params SqlParameter[] cmdParms)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, connection, null, SQLString, cmdParms);
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
try
{
da.Fill(ds, "ds");
cmd.Parameters.Clear();
}
catch (System.Data.SqlClient.SqlException ex)
{
throw new Exception(ex.Message);
}
return ds;
}
}
}
public static DataTable QueryTable(string SQLString, params SqlParameter[] cmdParms)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, connection, null, SQLString, cmdParms);
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
try
{
da.Fill(ds, "ds");
cmd.Parameters.Clear();
}
catch (System.Data.SqlClient.SqlException ex)
{
throw new Exception(ex.Message);
}
return ds.Tables[0];
}
}
}
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 parm in cmdParms)
cmd.Parameters.Add(parm);
}
}
#endregion
#region 儲存過程操作
/// <summary>
/// 執行儲存過程
/// </summary>
/// <param name="storedProcName">儲存過程名</param>
/// <param name="parameters">儲存過程引數</param>
/// <returns>SqlDataReader</returns>
public static SqlDataReader RunProcedure(string storedProcName, IDataParameter[] parameters)
{
SqlConnection connection = new SqlConnection(connectionString);
SqlDataReader returnReader;
connection.Open();
SqlCommand command = BuildQueryCommand(connection, storedProcName, parameters);
command.CommandType = CommandType.StoredProcedure;
returnReader = command.ExecuteReader();
return returnReader;
}
/// <summary>
/// 執行儲存過程
/// </summary>
/// <param name="storedProcName">儲存過程名</param>
/// <param name="parameters">儲存過程引數</param>
/// <param name="tableName">DataSet結果中的表名</param>
/// <returns>DataSet</returns>
public static DataSet RunProcedure(string storedProcName, IDataParameter[] parameters, string tableName)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
DataSet dataSet = new DataSet();
connection.Open();
SqlDataAdapter sqlDA = new SqlDataAdapter();
sqlDA.SelectCommand = BuildQueryCommand(connection, storedProcName, parameters);
sqlDA.Fill(dataSet, tableName);
connection.Close();
return dataSet;
}
}
/// <summary>
/// 構建 SqlCommand 物件(用來返回一個結果集,而不是一個整數值)
/// </summary>
/// <param name="connection">資料庫連線</param>
/// <param name="storedProcName">儲存過程名</param>
/// <param name="parameters">儲存過程引數</param>
/// <returns>SqlCommand</returns>
private static SqlCommand BuildQueryCommand(SqlConnection connection, string storedProcName, IDataParameter[] parameters)
{
SqlCommand command = new SqlCommand(storedProcName, connection);
command.CommandType = CommandType.StoredProcedure;
foreach (SqlParameter parameter in parameters)
{
command.Parameters.Add(parameter);
}
return command;
}
/// <summary>
/// 執行儲存過程,返回影響的行數
/// </summary>
/// <param name="storedProcName">儲存過程名</param>
/// <param name="parameters">儲存過程引數</param>
/// <param name="rowsAffected">影響的行數</param>
/// <returns></returns>
public static int RunProcedure(string storedProcName, IDataParameter[] parameters, out int rowsAffected)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
int result;
connection.Open();
SqlCommand command = BuildIntCommand(connection, storedProcName, parameters);
rowsAffected = command.ExecuteNonQuery();
result = (int)command.Parameters["ReturnValue"].Value;
//Connection.Close();
return result;
}
}
/// <summary>
/// 建立 SqlCommand 物件例項(用來返回一個整數值)
/// </summary>
/// <param name="storedProcName">儲存過程名</param>
/// <param name="parameters">儲存過程引數</param>
/// <returns>SqlCommand 物件例項</returns>
private static SqlCommand BuildIntCommand(SqlConnection connection, string storedProcName, IDataParameter[] parameters)
{
SqlCommand command = BuildQueryCommand(connection, storedProcName, parameters);
command.Parameters.Add(new SqlParameter("ReturnValue",
SqlDbType.Int, 4, ParameterDirection.ReturnValue,
false, 0, 0, string.Empty, DataRowVersion.Default, null));
return command;
}
#endregion
}
}