2016-04-14 51 views
4

Merhaba dost geliştiriciler,Linq sorgu listesi bellek kullanımı

Bir Linq sorgusunu kullanarak, Oracle veritabanında BLOB biçiminde depolanan XML nesneleri listesi ihracatını geliştirmek için çalışıyorum.

Ne yazık ki, BLOB'lardan biri oldukça büyük ve bellek kullanımı okurken 2 GB'a kadar büyüyor. Benim fileSet nesnesinin bir IQueryable<myRecord> nesnesi. Ben

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

ve

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

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

çalıştı Ama her zaman koç kullanıldığı konusunda bir listede büyük rekor çarptı. Dışa aktarımın oluşturulması için Buffer.BlockCopy'u kullanarak bazı kodları arıyordum, ancak bellek kullanımı nedeniyle bellek kullanımının azaltılması veya her blobun tembel yükünün nasıl kaldırılacağı hakkında bir fikriniz varsa, bu yönde daha fazla bir noktaya gerek yok.

+0

İşleminize bir blob yüklemeniz gerekiyor mu, yoksa bunun nedeni, fileSet'in kayıt tanımının bu blob alanına sahip olmasıdır? –

+0

@SergeyL Blob'a ihtiyacım var, bu yazılım bu bloğu yüklüyor ve xls dosyalarına aktarıyor, temelde xml içeride. Cevabınız için –

cevap

1

Sonunda linq ile hafızada hafif bir şey elde edemediğim için, linq ile dosyanın kimliğini aldıktan sonra, xml dosyasını akışlandırmak için OracleCommand kullandım.

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); 
     } 
    } 
} 
1

Birkaç çözüm var: 1) AsNoTracking() öğesini sorgunuza ekleyin. kayıtları veritabanı bağlamında önbelleğe olmayacak çünkü

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

AsNoTracking() serbest kayıtlarına çöp toplayıcısı yardımcı olur. Ama bildiğiniz gibi hemen harekete geçmez, tüketilen hafızada hala yerel bir artış olabilir. 2) Kaydınızın blob alanını içermeyen ve dosyaların listesini almayan ya da seçime yardımcı olabilecek bir ifade kullanarak kayıtlarınızın ayrı bir tanımını oluşturabilirsiniz, ancak bunun nasıl yapıldığını sql'ye nasıl çevirdiğinizi kontrol etmeniz gerekir.

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

Sonra bir damla olsun açıkça olacak her kaydını işleme

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

veya

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

Tanklar. Çünkü hala EF 4.0'da AsNoTracking() ' 'a erişimim yok, bu yüzden ben de' fileSet.SetMergeOption (MergeOption.NoTracking) 'yi denedim; Ama sonuç değişmedi, yine de Büyük blob ile nesne sonra bellek kullanımı yüklenir. Ancak, bu konuda arama yapmaya devam edeceğim ve belki de yöneticim tamam ise EF'imi güncelleyeceğim ^ –