linq SubmitChanges läuft der Speicher aus
-
28-09-2019 - |
Frage
habe ich eine Datenbank mit über 180.000 Datensätzen. Ich versuche, eine PDF-Datei zu jedem dieser Datensätze zu befestigen. Jede pdf ist etwa 250 kb groß. Doch nach etwa einer Minute meines Programm beginnt etwa um einen GB Speicher nehmen, und ich habe ihn zu stoppen. Ich habe versucht, es zu tun, so der Hinweis auf jedes Linq Objekt entfernt wird, sobald es aktualisiert wird, aber das scheint nicht zu helfen. Wie kann ich es den Verweis löschen?
Danke für Ihre Hilfe
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
Lösung
Ich schlage vor, Sie führen dies in den Reihen, mit Take
(< em> vor der Anruf an ToList
) eine bestimmte Anzahl von Elementen zu einem Zeitpunkt, zu verarbeiten. Read (sagen wir) 10, stellen Sie die PDFContent
auf alle von ihnen, Anruf SubmitChanges
, und dann wieder von vorne anfangen. (Ich bin nicht sicher, ob offhand Sie mit einem neuen DataContext
an diesem Punkt beginnen sollten, aber es könnte sauberste so zu tun.)
Als Nebenwirkung des Code den Inhalt einer Datei wird gebrochen in mindestens ein paar Möglichkeiten zu lesen - aber es wäre einfacher, nur zu verwenden File.ReadAllBytes
an erster Stelle.
Auch Ihr Weg, um die Liste nach und nach schrumpfen Handhabung ist wirklich ineffizient - nach 180.000 Datensätze zu holen, sind Sie dann den Aufbau eine neue Liste mit 179.999 Datensätze, dann noch mit 179.998 Datensätze etc
.Andere Tipps
Hat die Datacontext ObjectTrackingEnabled auf true gesetzt (der Standardwert)? Wenn ja, dann wird es versuchen, einen Datensatz zu halten im wesentlichen alle Daten, die er berührt, wodurch der Garbage Collector verhindert in der Lage, irgendetwas davon zu sammeln.
Wenn ja, sollten Sie in der Lage, die Situation zu beheben, indem Sie in regelmäßigen Abständen die Datacontext entsorgen und einen neuen zu erstellen, oder dreht Objektverfolgung aus.
OK. Um die kleinste Menge an Speicher zu verwenden, müssen wir die Datacontext in Blöcken aktualisieren. Ich habe einen Beispielcode unten setzen. Könnte sytax Fehler haben, da ich Notizblock bin mit ihm zu geben.
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
weiter zu optimieren die Geschwindigkeit Sie die recordID der in ein Array von AllItems als anonymer Typ und Satz DelayLoading auf für das PDF-Feld erhalten.