none
Windows Service 寫入資料庫SQL Server 問題 RRS feed

  • 問題

  • 請問各位前輩,

    小弟利用 VS 2008 C# 建立一 Windows Service ,此 Service 主要目的為將資料寫入資料庫,
    但是我發現到 Service 可以正常運作但是就是無法寫入資料庫,滿奇怪的,我的程式碼如下

    using System.Data.SqlClient;

    SqlConnection cn = new SqlConnection(ConfigurationSettings.AppSettings["SQLConnection"]);
    SqlTransaction tran;
    SqlCommand cmd;

    cn.Open();

    tran = cn.BeginTransaction(); // create transaction
    cmd = new SqlCommand(SQL, cn, tran);

    我有寫 Event Log 去追蹤,但是發現每次只要運作到 Cn.Open 時,就運作不下去了,也不會跳到 Try Catch 裡面的 Exception 中,就這樣完全不知道原因,不知道是哪邊出現問題。

    謝謝各位前輩指導。

    2009年10月14日 上午 02:31

解答

  • 為攔截到例外應該是你的例外處理部分有問題,可能是你的Transaction已經忽略掉例外狀況,所以上一層例外攔截才未攔到例外.


    寫Windows Service如果沒有做Unit Test.我建議在撰寫與測試時使用Console Mode,在發布時才將程式轉為Windows Service.
    使用Console Mode來Debug程式會很簡單.當然有時候Console Mode可能運作正常而Windows Service才發生問題,這時候就必須使用VS IDE中的Attach to Process功能(在Debug選單中),偵錯Windows Service.
    但通常除非必要不會使用這種方式,原則上程式在開發中都使用Console Mode來處理.

    至於作法這邊提供一種做法
    建立一個Solution
    新增建立一個Console Mode Application
    新增建立一個Windows Service Application
    新增建立一個Class Library專案,把你的真正程式放在這邊.

    Console Mode Application參考使用Class Library專案.
    Windows Service Application參考使用Class Library專案.

    所以Console Mode Application與Windows Service Application本身幾乎沒有甚麼程式碼.這樣就能隨時使用Console Mode來開發偵錯程式,Windows Service部分用來做部屬時使用.

    • 已標示為解答 Andychen74 2009年10月14日 上午 05:05
    2009年10月14日 上午 03:17
  • 至於Class部分之程式碼做法其實很簡單,就是把原來Windows Service的Start() Stop()等程式放到一個新的Class中
    譬如
    class MyService
    {
    public void Start()
    {
    ...
    }
    
    public void STop();
    {
    ...
    }
    
    }
    而Windows Service與Console Mode主程式就會很單純如下使用
    //Console Mode程式
    ... Main()
    {
    MyService service = new MyService();
    service.Start();
    
    Console.Read();
    
    service.Stop();
    }
    
    //Windows Service程式
    
    class YourWindowsService
    {
    MyService service = new MyService();
    
    ...Start()
    {
    service.Start();
    }
    
    
    ...Stop()
    {
    service.Stop();
    }
    
    }
    • 已標示為解答 Andychen74 2009年10月14日 上午 05:05
    2009年10月14日 上午 03:25

所有回覆

  • HI,

    可能是Windows Service的執行身分無法登入資料庫, 您可以到利用事件檢視器檢視詳細的錯誤訊息, 如果是Windows Service的執行身分無法登入資料庫, 就使用SQL Server Management Studio開始必要的權限即可.
    2009年10月14日 上午 02:43
  • 請問 This 前輩,

    我有去查詢事件檢視器中的資訊,沒有發現到有任何錯誤資訊,只有記錄這支 Service 的啟動與停止資訊,
    另外我在服務中設定此 Service -> 右鍵 -> 內容 -> 登入 -> 我輸入 Administrator 與密碼為最大權限。
    我連接資料庫要去 Insert 資料時我是利用 sa 登入,但是還是不行,滿奇怪的狀況。

    謝謝!!
    2009年10月14日 上午 03:10
  • 為攔截到例外應該是你的例外處理部分有問題,可能是你的Transaction已經忽略掉例外狀況,所以上一層例外攔截才未攔到例外.


    寫Windows Service如果沒有做Unit Test.我建議在撰寫與測試時使用Console Mode,在發布時才將程式轉為Windows Service.
    使用Console Mode來Debug程式會很簡單.當然有時候Console Mode可能運作正常而Windows Service才發生問題,這時候就必須使用VS IDE中的Attach to Process功能(在Debug選單中),偵錯Windows Service.
    但通常除非必要不會使用這種方式,原則上程式在開發中都使用Console Mode來處理.

    至於作法這邊提供一種做法
    建立一個Solution
    新增建立一個Console Mode Application
    新增建立一個Windows Service Application
    新增建立一個Class Library專案,把你的真正程式放在這邊.

    Console Mode Application參考使用Class Library專案.
    Windows Service Application參考使用Class Library專案.

    所以Console Mode Application與Windows Service Application本身幾乎沒有甚麼程式碼.這樣就能隨時使用Console Mode來開發偵錯程式,Windows Service部分用來做部屬時使用.

    • 已標示為解答 Andychen74 2009年10月14日 上午 05:05
    2009年10月14日 上午 03:17
  • 至於Class部分之程式碼做法其實很簡單,就是把原來Windows Service的Start() Stop()等程式放到一個新的Class中
    譬如
    class MyService
    {
    public void Start()
    {
    ...
    }
    
    public void STop();
    {
    ...
    }
    
    }
    而Windows Service與Console Mode主程式就會很單純如下使用
    //Console Mode程式
    ... Main()
    {
    MyService service = new MyService();
    service.Start();
    
    Console.Read();
    
    service.Stop();
    }
    
    //Windows Service程式
    
    class YourWindowsService
    {
    MyService service = new MyService();
    
    ...Start()
    {
    service.Start();
    }
    
    
    ...Stop()
    {
    service.Stop();
    }
    
    }
    • 已標示為解答 Andychen74 2009年10月14日 上午 05:05
    2009年10月14日 上午 03:25