1

私は約180,000レコードのデータベースを持っています。これらの各レコードにPDFファイルを添付しようとしています。各PDFのサイズは約250kbです。ただし、約1分後、プログラムは約GBのメモリを消費し始め、停止する必要があります。更新すると各linqオブジェクトへの参照が削除されるように試してみましたが、役に立たないようです。どうすれば参照を明確にできますか?

ご協力いただきありがとうございます

Private Sub uploadPDFs(ByVal args() As String)
    Dim indexFiles = (From indexFile In dataContext.IndexFiles
                     Where indexFile.PDFContent = Nothing
                     Order By indexFile.PDFFolder).ToList
    Dim currentDirectory As IO.DirectoryInfo
    Dim currentFile As IO.FileInfo
    Dim tempIndexFile As IndexFile

    While indexFiles.Count > 0
        tempIndexFile = indexFiles(0)
        indexFiles = indexFiles.Skip(1).ToList
        currentDirectory = 'I set the directory that I need
        currentFile = 'I get the file that I need
        writePDF(currentDirectory, currentFile, tempIndexFile)
    End While
End Sub

Private Sub writePDF(ByVal directory As IO.DirectoryInfo, ByVal file As IO.FileInfo, ByVal indexFile As IndexFile)
    Dim bytes() As Byte
    bytes = getFileStream(file)
    indexFile.PDFContent = bytes
    dataContext.SubmitChanges()
    counter += 1
    If counter Mod 10 = 0 Then Console.WriteLine("     saved file " & file.Name & " at " & directory.Name)
End Sub


Private Function getFileStream(ByVal fileInfo As IO.FileInfo) As Byte()
    Dim fileStream = fileInfo.OpenRead()
    Dim bytesLength As Long = fileStream.Length
    Dim bytes(bytesLength) As Byte

    fileStream.Read(bytes, 0, bytesLength)
    fileStream.Close()

    Return bytes
End Function
4

3 に答える 3

4

一度に特定の数のアイテムを処理するためにTake(を呼び出すに)を使用して、これをバッチで実行することをお勧めします。ToList(たとえば)10を読み、それらすべてPDFContentにを設定し、を呼び出してから、最初からやり直します。(その時点で新しいものから始めるべきかどうかはわかりませんが、そうするのが最もクリーンかもしれません。)SubmitChangesDataContext

余談ですが、ファイルの内容を読み取るためのコードは、少なくとも2つの方法で壊れていますが、File.ReadAllBytesそもそも使用する方が簡単です。

また、リストを徐々に縮小して処理する方法は、実際には非効率的です。180,000レコードをフェッチした後、179,999レコードの新しいリストを作成し、次に179,998レコードのリストを作成します。

于 2010-11-25T16:14:23.283 に答える
0

DataContextのObjectTrackingEnabledがtrue(デフォルト値)に設定されていますか?その場合、アクセスする本質的にすべてのデータの記録を保持しようとするため、ガベージコレクターはそのデータを収集できなくなります。

その場合は、DataContextを定期的に破棄して新しいものを作成するか、オブジェクトトラッキングをオフにすることで、状況を修正できるはずです。

于 2010-11-25T16:22:01.943 に答える
0

わかった。最小量のメモリを使用するには、データコンテキストをブロック単位で更新する必要があります。以下にサンプルコードを示します。メモ帳を使用して入力しているため、構文エラーが発生する可能性があります。

    Dim DB as YourDataContext = new YourDataContext
    Dim BlockSize as integer = 25
    Dim AllItems = DB.Items.Where(function(i) i.PDFfile.HasValue=False)

    Dim count = 0
    Dim tmpDB as YourDataContext = new YourDataContext


While (count < AllITems.Count)

    Dim _item = tmpDB.Items.Single(function(i) i.recordID=AllItems.Item(count).recordID)
    _item.PDF = GetPDF()

    Count +=1

    if count mod BlockSize = 0 or count = AllItems.Count then
        tmpDB.SubmitChanges()
         tmpDB =  new YourDataContext
           GC.Collect()
    end if

End While

速度をさらに最適化するために、すべてのアイテムから匿名型としてrecordIDを配列に取得し、そのPDFフィールドに対してDelayLoadingをオンに設定できます。

于 2010-12-01T00:14:11.667 に答える