1. 程式人生 > >利用Topshelf搭建Windowns服務實現定期自動新增資料邏輯和原理

利用Topshelf搭建Windowns服務實現定期自動新增資料邏輯和原理

一、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
    }
}