Linq查询blob列表,内存使用情况

时间:2016-04-14 08:18:55

标签: c# linq memory blob

Hello开发人员,

我正在尝试使用Linq查询改进在Oracle数据库中以BLOB格式存储的XML对象列表的导出。

可悲的是,其中一个BLOB非常大,当我阅读时,内存使用量增长到2 GB。我的fileSet对象是IQueryable<myRecord>对象。 我试过了

foreach (var file in fileSet){...}

var files = fileSet.ToList(); //This time the list is causing the memory load.
foreach(file in files){...}

var e = fileSet.AsEnumerable().GetEnumerator();
while(e.MoveNext()){...}

但是每当我打到列表中的大记录时,ram就会被过度使用。 为了创建导出,我正在寻找使用Buffer.BlockCopy的一些代码但是由于内存过量充电,如果你有一些想法如何减少内存使用量或延迟加载,那么在这个方向上没有任何意义blob :(

2 个答案:

答案 0 :(得分:1)

有几种解决方案: 1)将AsNoTracking()添加到您的查询中。

fileSet.AsNoTracking() or fileSet.AsNoTracking().Where(...) 

AsNoTracking()帮助垃圾收集器释放记录,因为记录不会缓存在数据库上下文中。但是,正如您所知道的那样,它不会立即起作用,您可能会在本地消耗内存增加。

2)您可以创建一个单独的记录定义,该记录不包含blob字段并通过它获取文件列表或使用select表达式它也可能有帮助,但您应该检查它是如何转换为sql < / p>

fileSet.AsNoTracking().Select(x=>new { x.Id, x.Name })

然后处理每条记录,你将明确得到一个blob

var myblob = model.Database
    .SqlQuery<string>("select myblob from mytable where id=@id", 
         new SqlParameter("@id", System.Data.SqlDbType.Int) { Value = myId })
    .FirstOrDefault();

var myBlob = fileSet
       .AsNoTracking()
       .Select(x=>new { x.Blob )
       .FirstOrDefault(x=>x.ConfigId=myId);

答案 1 :(得分:1)

最后因为我无法使用linq在内存中设置一些亮点,所以在使用linq获取文件的ID之后,我使用OracleCommand来传输xml文件。

using (var reader = cmd.ExecuteReader())
{
   while (reader.Read())
   {
      var blob = reader.GetOracleLob(0);
      var buffer = new byte[128];
      using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Write))
      {
          blob.CopyTo(fs);
      }
   }
}