C# 读取4000个文件后引发System.OutOfMemoryException
我们希望将52000个文件(C# 读取4000个文件后引发System.OutOfMemoryException,c#,entity-framework,sql-server-2012,C#,Entity Framework,Sql Server 2012,我们希望将52000个文件(.pdf,.xls,.doc…等)导入SQL Server 2012数据库 我有一个docsier\u fichier.txt文件,其中包含文件名。我将这些名称加载到一个集合中,然后循环此集合,并尝试在direcotryPiecesJointes中查找这些文件,并将它们转换为字节,然后使用以下代码将它们插入数据库: var dossierFichiers = addOrUpdateHelper.ReadEntities<DossierFichier, Dossi
.pdf
,.xls
,.doc
…等)导入SQL Server 2012数据库
我有一个docsier\u fichier.txt
文件,其中包含文件名。我将这些名称加载到一个集合中,然后循环此集合,并尝试在direcotryPiecesJointes
中查找这些文件,并将它们转换为字节,然后使用以下代码将它们插入数据库:
var dossierFichiers = addOrUpdateHelper.ReadEntities<DossierFichier, DossierFichierMap>("dossier_fichier.txt").ToArray();
// (2) Parcourir toutes les instances de DossierFichier chargées + Lire le fichier référencé + Le charger dans la propriété Fichier
var dirPath = System.IO.Path.Combine(Environment.CurrentDirectory, "piecesJointes");
var nbfichier = 0;
foreach (var df in dossierFichiers) {
try {
var path = System.IO.Path.Combine(dirPath, string.Concat( df.Code,"_", df.Nom));
df.Fichier = File.ReadAllBytes(path);
context.DossierFichier.Add(df);
context.SaveChanges();
Logger.Info("Le fichier {0} a été inséré", df.Nom);
nbfichier++;
} catch (FileNotFoundException ex) {
Logger.Error("Fichier {0} : {1}", df.Nom, ex.Message);
} catch (Exception ex) {
Logger.Error("Fichier {0} : {1}",df.Nom, ex.Message);
}
}
var-dossierfichers=addorupdatehelp.ReadEntities(“dossier_fichier.txt”).ToArray();
//(2)包裹商兜售档案保管员的实例+文件保管员的权利+文件保管员的权利+文件保管员的权利
var dirPath=System.IO.Path.Combine(Environment.CurrentDirectory,“片段点”);
var nbfichier=0;
foreach(档案编制者中的var df){
试一试{
var path=System.IO.path.Combine(dirPath,string.Concat(df.Code,“”,df.Nom));
df.Fichier=File.ReadAllBytes(路径);
上下文。档案编制者。添加(df);
SaveChanges();
Logger.Info(“lefichier{0}aétéinséré”,df.Nom);
nbfichier++;
}捕获(FileNotFoundException ex){
Logger.Error(“Fichier{0}:{1}”,df.Nom,ex.Message);
}捕获(例外情况除外){
Logger.Error(“Fichier{0}:{1}”,df.Nom,ex.Message);
}
}
插入4000个文件后,我得到了一个
OutOFMemoryException
,这花费了很多时间(60小时)。请您帮助我插入所有这些文件而不获取OutOfmemoryException
,以及如何更快地插入这些文件?对于集合中的每个项目,您可以将整个文件内容(字节数组)添加到df.Fichier
。这是内存使用量增加的原因之一
您可以通过使用临时变量来解决此特定问题 您的代码似乎具有O(n2)性能,因为它将所有文件内容保留在内存中
- 循环的第一次迭代将保存添加的第一个对象
- 第二次迭代保存第二个对象并刷新第一个对象
- 第三次迭代保存第三个对象并刷新前两个对象
- 。。。等等
- 第N次迭代插入第N个对象,并刷新以前插入的N-1个对象
- 添加到目前为止已插入的对象数
- 不要调用
context.SaveChanges()代码>立即
- 当插入的对象数达到100时,调用
context.SaveChanges()代码>,然后将
替换为新实例上下文
df.Fichier
中,可以保留文件内容。这可能会导致系统内存不足,因此您应该复制df
:
var path = System.IO.Path.Combine(dirPath, string.Concat( df.Code,"_", df.Nom));
var dfCopy = new DossierFichier(df); // Copy df's fields
dfCopy.Fichier = File.ReadAllBytes(path);
context.DossierFichier.Add(dfCopy);
您的系统将没有无限内存,您可能需要定期将数据保存出来,然后再进行处理。或者甚至读一个文件,做你需要做的事情,然后从内存中删除它。我怎样才能显示它?如何从32位进程中运行的内存中删除它?另外,最好为每个插入创建新的实体框架上下文,并分别加载每个实体,不要重用上下文和实体。不知道什么是
docsierficher
我不知道。这取决于为什么需要这些文件字节。如果你只是读取字节并将它们存储在某个地方,我的答案将不同于你是否需要程序长度的所有内存。就这样。出于好奇,文件的平均大小是多少?或者只是为每次更新创建新的上下文,通常也可以。您可能也应该注意将字节保存在内存中,即df.Fichier=File.ReadAllBytes(path)代码>即使使用您描述的更新,由于所有这些字节都在内存中,仍有可能内存不足。@如果您是对的,我没有意识到内容保存在循环变量的Fichier
字段中。谢谢你的评论!我为每个文件添加了一个DbContext,但仍然有outofmemoryexception@amina诀窍是确保先前文件的DbContext
s在不再需要时被丢弃,并且在调用context.SaveChanges()时设置df.Fichier=null
已成功返回。创建字节后如何释放内存?我为每个文件添加了DbContext,但仍有outofmemoryexception@Evk我为每个文件添加了一个DbContext,但仍然存在outofmemory异常