linq subbitchanges耗尽了内存
-
28-09-2019 - |
题
我有一个数据库,约有180,000个记录。我正在尝试将PDF文件附加到每个记录中。每个PDF的大小约为250 kb。但是,大约一分钟后,我的程序开始大约有一个GB的内存,我必须停止它。我尝试执行此操作,因此对每个LINQ对象进行更新后将删除对每个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
解决方案
我建议您使用 Take
(前 打电话 ToList
)一次处理特定数量的项目。阅读(说)10,设置 PDFContent
在 全部 他们打电话 SubmitChanges
, ,然后重新开始。 (我不确定您是否应该从新的 DataContext
那时,这样做可能最干净。)
顺便说一句,您的读取文件内容的代码至少以几种方式破坏了 - 但是仅使用的代码会更简单 File.ReadAllBytes
首先。
另外,您处理清单的方式逐渐缩小确实效率低下 - 在获取了180,000个记录后,您就可以构建一个具有179,999个记录的新列表,然后又有179,998的记录等。
其他提示
DataContext是否将ObjectTrackingEnabled设置为true(默认值)?如果是这样,那么它将尝试保留其触摸的所有数据的记录,从而阻止垃圾收集器能够收集任何数据。
如果是这样,您应该能够通过定期处置DataContext并创建新的情况或关闭对象跟踪来解决这种情况。
好的。要使用最少量的内存,我们必须在块中更新DataContext。我在下面放了一个示例代码。可能会有Sytax错误,因为我使用记事本将其输入。
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作为匿名类型从Allitems中列入数组,并为该PDF字段设置延迟加载。
不隶属于 StackOverflow