none
Connection已關閉但無法刪除mdb檔案 RRS feed

  • 一般討論

  • 各位好~

    我有一支console mode的程式,打開mdb做相關商業邏輯的處理動作,執行完畢後,我非常的確定connection的state是close,且Dispose()及被設為Nothing。

    如果我用Debug Mode去執行,close之後,ldb檔已不存在,可以正常的刪掉mdb,

    但如果直接以.exe執行,close之後,ldb檔仍存在且出現 "另一個處理序正在使用"的錯誤訊息,我知道這個訊息是因為mdb,所以會產生ldb檔。可是connection的狀態已經是close的...

    請問是哪方面的問題呢?

    2011年3月6日 上午 07:33

所有回覆

  • 關掉連線, 丟棄連線物件之後, 再加一個動作:

    GC.Collect()

    看看是否OK?

    2011年3月6日 上午 07:58
  • 你好~

    還是一樣有處理序正在使用,無法刪除。

    2011年3月6日 上午 08:14
  • 如果你的OS是Windows 7,可以參考下面的文章,看是否能幫你找出哪個程式占用MDB檔。

    http://ck101.com/viewthread.php?tid=1772742


    http://www.dotblogs.com.tw/terrychuang/
    2011年3月6日 上午 11:58
  • 如果你的OS是Windows 7,可以參考下面的文章,看是否能幫你找出哪個程式占用MDB檔。

    http://ck101.com/viewthread.php?tid=1772742


    http://www.dotblogs.com.tw/terrychuang/


    To TerryChuang :

    你好,很抱歉我的作業系統是xp....

    2011年3月6日 下午 01:23
  • 你用拖拉產生的自動物件處理連線還是自己用 ADO.NET 來處理連線?

     


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2011年3月6日 下午 02:54
  • 你用拖拉產生的自動物件處理連線還是自己用 ADO.NET 來處理連線?

     


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    你好,我以OleDbConnection做連線。OleDbConnection變數宣告為全域變數,在主程式中Open() ,與mdb相關的處理有

    1.中間有開OldebDataReader,不過在Function離開前,也都確實Close()掉

    2.sql執行Bulkinsert,Bulkinsert的來源是OldebDataReader,Bulkinsert變數以Using區塊寫,這個應該沒有影響mdb吧?

    3.在刪除檔案之前,先確認OleDbConnection的State,若為Open(),則執行Close,再刪除檔案。

    2011年3月7日 上午 04:09
  • Hi,

    >>3.在刪除檔案之前,先確認OleDbConnection的State,若為Open(),則執行Close,再刪除檔案。

    可以改用Dispose把OleDbConnection釋放看看

    或是檢查看看是不是有造多個Connection出來

    還是不行的話~把程式碼貼出來看看吧


    謙卑學習,持之以恆,才能不斷的Level Up http://www.dotblogs.com.tw/larrynung/
    2011年3月7日 上午 05:04
  • Hi,

    >>3.在刪除檔案之前,先確認OleDbConnection的State,若為Open(),則執行Close ,再刪除檔案。

    可以改用Dispose把OleDbConnection 釋放看看

    或是檢查看看是不是有造多個Connection出來

    還是不行的話~把程式碼貼出來看看吧


    謙卑學習,持之以恆,才能不斷的Level Up http://www.dotblogs.com.tw/larrynung/

    你好~我有作Dispose() 以及設為Nothing,結果是一樣的。是Debug mode下斷點的執行模式與直接執行exe檔不一樣嗎?

    程式碼如下:

    主進入點為 MainBCIImport --> DoBCIImport (1. 開啟mdb, 2. 開啟sql , 3. sql bulkinsert 資料來源為OledbDataReader)

     

     Public Sub MainBCIImport()
      If DoBCIImport(tmpFileName) = False Then
        ImportFail(dsFileImport.ZT_FileImportLog.Rows(intFileCount), dbo)
      Else
        ImportSucess(dsFileImport.ZT_FileImportLog.Rows(intFileCount), dbo)
      End If
    
      If False = IsNothing(cnnMDB) Then
       If cnnMDB.State = ConnectionState.Open Then cnnMDB.Close()
       cnnMDB.Dispose()
       cnnMDB = Nothing
      End If
    
      '刪除暫存檔
      If File.Exists(FileIO.FileSystem.CombinePath(strLocoalPath, tmpFileName)) = True Then
       File.Delete(FileIO.FileSystem.CombinePath(strLocoalPath, tmpFileName)) '刪除檔案
      End If
     End Sub

    Private Function DoBCIImport(ByVal tmpFileName As String) As Boolean
    Dim connStr As String = "Provider=""Microsoft.Jet.OLEDB.4.0"";" & _
    "Data Source=""" & strFilePath & """;" & _
    "Mode=Share Deny None;" & _
    "persist security info=False;"
    cnnMDB = New OleDbConnection(connStr)
    '** Open Access **
    Try
    cnnMDB.Open()
    Catch ex As Exception
    sbError.AppendLine("cnnMDB.Open-開啟MDB資料庫失敗!")
    Exit Function
    End Try
    '** 格式檢核 **
    If CheckMDBValidate(cnnMDB) = False Then
    cnnMDB.Close()
    Exit Function
    Else
    sbError.AppendLine("CheckMDBValidate-檢查MDB資料庫格式成功!")
    End If
    ** Open SQL DB **
    Using cnnTemp As SqlConnection = New SqlConnection(strConnectionString)
    cnnTemp.Open()

    Dim params(0) As SqlParameter
    If CreateSqlCommand(cnnIDRTemp, "HandleTemp", params) = False Then
    cnnIDRTemp.Close()
    Exit Function
    Else
    sbError.AppendLine("清空Temp資料庫成功!")
    End If
    If BulkInsertIOWHisLog(cnnTemp) = False Then
    cnnMDB.Close()
    cnnIDRTemp.Close()
    Exit Function
    Else
    sbError.AppendLine("BulkInsertHisLog-匯入完成")
    End If

    ' 以下會作多個重複的BulkInsert動作
    End Using
    End Function

    Private Function BulkInsertPaymentHistory(ByRef cnnTemp As SqlConnection) As Boolean
    strSQL = " SELECT [passport_no] as PassportNo, [escrow_account_no], [posting_date]," + _
    " [payment_date] as PaymentDate, [payable_date] as PayableDate, [channel_code], " + _
    " [amount] as PaymentAmount, [source] as Source, [pay_code] as PayCode ,[payment_history_no] as SequenceNo" +_
    " ,Null as AsOfDate,0 as ModifyUserID,[product_type] as ProductCode" + _
    " FROM PaymentHistory "
    strSQLCount = "SELECT Count([passport_no]) as RCount FROM PaymentHistory "

    If BulkInsertHanlder("BulkInsertPaymentHistory", "dbo.PaymentHistory", strSQL, strSQLCount, cnnTemp) = False Then
    Return False
    Else
    Return True
    End If
    End Function

    Private Function BulkInsertHanlder(ByVal EventHanlder As String, ByVal DestinationTableName As String, _
    ByVal strSQL As String, ByVal strSQLCount As String _
    , ByRef cnnTemp As SqlConnection) As Boolean

    sbError.AppendLine(EventHanlder & "匯入開始:" & DestinationTableName)
    Dim myWatch As Stopwatch = New Stopwatch()
    Dim MDBReaderCount As OleDbDataReader = Nothing
    Dim MDBReader As OleDbDataReader = Nothing
    Try
    myWatch.Start()
    Dim MDBSourceCount As OleDbCommand = New OleDbCommand(strSQLCount, cnnMDB)
    MDBReaderCount = MDBSourceCount.ExecuteReader
    Dim intMDBCount As Integer '目前處理的資料表資料筆數

    If MDBReaderCount.HasRows = True Then
    If MDBReaderCount.Read = True Then
    intMDBCount = MDBReaderCount.GetInt32(0)
    End If
    End If
    MDBReaderCount.Close()
    MDBReaderCount.Dispose()
    MDBReaderCount = Nothing

    Dim MDBSourceData As OleDbCommand = New OleDbCommand(strSQL, cnnMDB)
    MDBReader = MDBSourceData.ExecuteReader
    Using bcp As SqlBulkCopy = New SqlBulkCopy(cnnTemp)
    bcp.NotifyAfter = 1000
    bcp.DestinationTableName = DestinationTableName

    bcp.BatchSize = 1000
    bcp.BulkCopyTimeout = 1200
    bcp.WriteToServer(MDBReader)
    myWatch.Stop()
    If (Convert.ToBoolean(Convert.ToInt32(myWatch.ElapsedMilliseconds) > 1000)) Then
    sbError.AppendLine(EventHanlder & "處理時間:" & Convert.ToString(myWatch.ElapsedMilliseconds / 1000) & _
     " sec, 資料筆數:" & intMDBCount)
    Else
    sbError.AppendLine(EventHanlder & "處理時間:" & myWatch.ElapsedMilliseconds.ToString() & _
     " ms, 資料筆數:" & intMDBCount)
    End If
    End Using

    MDBReader.Close()
    MDBReader.Dispose()
    MDBReader = Nothing
    Return True
    Catch ex As Exception
    CommonSystemLog.WriteLog(ex)

    If IsNothing(MDBReader) = False AndAlso MDBReader.IsClosed() = False Then
    MDBReader.Close()
    MDBReader.Dispose()
    MDBReader = Nothing
    End If
    If IsNothing(MDBReaderCount) = False AndAlso MDBReaderCount.IsClosed() = False Then
    MDBReaderCount.Close()
    MDBReaderCount.Dispose()
    MDBReaderCount = Nothing
    End If

    Return False
    End Try

    End Function

     

    2011年3月7日 上午 10:49
  • Hi,

    因為前後描述不同~另外也怕是人為操作的疏失~所以才再請你確認一下

    若確定是Debug時OK~Release時有問題

    通常是因為沒有給到初始值

    稍微看了一下程式~DoBCIImport這道方法比較可疑一點

    我找不到你有傳出回傳值

    也不確定該方法是否會被重覆叫用產生多個Connection

    另外Connection物件是全域的又被傳來傳去

    不確定是否有未被釋放的物件佔用

    但起碼看來函式內的Reader都未釋放

    建議秀出訊息確認Release是否有重複建立Connection、是否關鍵程式都確定有執行到(像是檢查是否在關閉連線前跳出了Function)

    或是建ㄧ個乾淨的專案先測試看看~~

     


    謙卑學習,持之以恆,才能不斷的Level Up http://www.dotblogs.com.tw/larrynung/
    2011年3月7日 下午 02:44
  • Hi,

    因為前後描述不同~另外也怕是人為操作的疏失~所以才再請你確認一下

    若確定是Debug時OK~Release時有問題

    通常是因為沒有給到初始值

    稍微看了一下程式~DoBCIImport這道方法比較可疑一點

    我找不到你有傳出回傳值

    也不確定該方法是否會被重覆叫用產生多個Connection

    另外Connection物件是全域的又被傳來傳去

    不確定是否有未被釋放的物件佔用

    但起碼看來函式內的Reader都未釋放

    建議秀出訊息確認Release是否有重複建立Connection、是否關鍵程式都確定有執行到(像是檢查是否在關閉連線前跳出了Function)

    或是建ㄧ個乾淨的專案先測試看看~~

     


    謙卑學習,持之以恆,才能不斷的Level Up http://www.dotblogs.com.tw/larrynung/


    你好~

    * 不好意思,DoBCIImport 做的事情實在太多了(BulkInser及Sql指令),所以沒把程式複製好....@@

    * Connection是使用ByRef 來傳遞參數,請問這樣是用同一條連線吧...是嗎?

    * 另外Reader,我在使用完畢時,有將它Close()、Dispose() 、set Nothing,以防萬一,所以在Try Catch Finally 時又在判斷是否關閉。

    * 我是在Debug mode 下斷點停在 mdb Connection 被Close()那行,同時去開啟TempFolder視窗,看看 mdb是否有被 lock住(若開啟mdb,ldb將存在),確實會在Close之後,ldb會自動消失,這時後去執行File.Delet ,就不會產生有處理序佔住。不過若是用Debug或是Release產生的 exe檔執行,就會有處理序佔住.....所以,我就用讓它在Close之後 Sleep 3秒,同樣用exe 來執行也是會出現錯誤。

    * 還有一點是,我執行這個exe時,大概會需要幾10分鐘的時間(5~7個Table,每個Table大概有己十萬筆資料要從mdb Insert 到 sql db),會有可能是因為連接時間太久了,就算我下Close()、Dispose() 、set Nothing,也沒有真正的回收 Connection嗎

    * 請問你指的 " 秀出訊息確認Release是否有重複建立Connection ",是Console.WriteLine 訊息嗎 ?

    非常感謝您的回答....謝謝~

    2011年3月8日 上午 02:13
  • * 不好意思,DoBCIImport 做的事情實在太多了(BulkInser及Sql指令),所以沒把程式複製好....@@

    * Connection是使用ByRef 來傳遞參數,請問這樣是用同一條連線吧...是嗎?

    * 另外Reader,我在使用完畢時,有將它Close()、Dispose() 、set Nothing,以防萬一,所以在Try Catch Finally 時又在判斷是否關閉。

    * 我是在Debug mode 下斷點停在 mdb Connection 被Close()那行,同時去開啟TempFolder視窗,看看 mdb是否有被 lock住(若開啟mdb,ldb將存在),確實會在Close之後,ldb會自動消失,這時後去執行File.Delet ,就不會產生有處理序佔住。不過若是用Debug或是Release產生的 exe檔執行,就會有處理序佔住.....所以,我就用讓它在Close之後 Sleep 3秒,同樣用exe 來執行也是會出現錯誤。

    * 還有一點是,我執行這個exe時,大概會需要幾10分鐘的時間(5~7個Table,每個Table大概有己十萬筆資料要從mdb Insert 到 sql db),會有可能是因為連接時間太久了,就算我下Close()、Dispose() 、set Nothing,也沒有真正的回收 Connection嗎

    * 請問你指的 " 秀出訊息確認Release是否有重複建立Connection ",是Console.WriteLine 訊息嗎 ?

    非常感謝您的回答....謝謝~

    看起來你的Connection是同一條
    Reader部分看來是我打錯~應該是指Command~Command有實作IDisposable~卻未釋放
    秀出訊息可能是指用Messagebox或是透過Debug.WriteLine搭配DebugView觀看
    以確定程式如你預期去運作
    會要請你確定關閉是因為GC並不是即時回收的
    每一個回收世代都有自己的回收週期
    就算物件有被Dispose~也只是即時釋放非託管的資源~只要有被存活的物件參考到~該物件仍是無法被回收

    你的程式將連線傳來傳去已經不好追到問題了
    既然連線參數是全域的~應該是不需要在傳遞
    在連線的建立上~你也並未判斷是否已經建立連線~而直接就New出來
    當該函式被頻繁叫用~就會產生許多不必要的連線物件

    另外要釐清的是...你的測試時關閉連線的動作是透過按鈕觸發?還是要關閉整個應用程式?處理序佔住是指應用程式關閉後仍有處理序殘留?

    謙卑學習,持之以恆,才能不斷的Level Up http://www.dotblogs.com.tw/larrynung/
    2011年3月8日 上午 02:47