2008-09-23 24 views
20

Tôi đã gặp một số vấn đề với LINQ-To-SQL xung quanh việc sử dụng bộ nhớ. Tôi đang sử dụng nó trong một dịch vụ Windows để làm một số xử lý, và tôi đang lặp qua một lượng lớn dữ liệu mà tôi đang kéo trở lại từ ngữ cảnh. Có - Tôi biết tôi có thể làm điều này với một thủ tục được lưu trữ nhưng có những lý do tại sao đó sẽ là một giải pháp ít hơn lý tưởng.Làm thế nào để tránh rò rỉ bộ nhớ bằng LINQ-To-SQL?

Dù sao, những gì tôi nhìn thấy cơ bản là bộ nhớ không được phát hành ngay cả sau khi tôi gọi context.SubmitChanges(). Vì vậy, tôi cuối cùng phải làm tất cả những thứ kỳ quặc như chỉ kéo lùi 100 bản ghi vào thời gian, hoặc tạo ra một số bối cảnh và khiến tất cả họ thực hiện các nhiệm vụ riêng biệt. Nếu tôi giữ nguyên DataContext và sử dụng nó sau này cho các cuộc gọi khác, nó chỉ ăn ngày càng nhiều bộ nhớ. Ngay cả khi tôi gọi Clear() trên mảng "var tableRows" mà truy vấn trả lại cho tôi, đặt thành giá trị rỗng và gọi SYstem.GC.Collect() - nó vẫn không giải phóng bộ nhớ.

Bây giờ tôi đã đọc một số cách bạn nên sử dụng nhanh chóng và loại bỏ chúng một cách nhanh chóng, nhưng có vẻ như chúng phải là một cách để buộc bối cảnh đổ tất cả dữ liệu của nó (hoặc tất cả dữ liệu theo dõi của nó) bảng cụ thể) tại một thời điểm nhất định để đảm bảo bộ nhớ là miễn phí.

Bất kỳ ai biết các bước nào đảm bảo rằng bộ nhớ được giải phóng?

Trả lời

15

Nếu bạn không cần phải theo dõi đối tượng thiết lập DataContext.ObjectTrackingEnabled-sai. Nếu bạn cần nó, bạn có thể sử dụng phản chiếu để gọi nội bộ DataContext.ClearCache(), mặc dù bạn phải biết rằng kể từ khi nội bộ của nó, nó có thể biến mất trong một phiên bản tương lai của khuôn khổ. Và theo như tôi có thể nói, khung chính nó không sử dụng nó nhưng nó hiện xóa bộ nhớ cache đối tượng.

+1

Lưu ý rằng như các quý ông khác đã nói, có lẽ tốt hơn là nên sử dụng nhiều DataContexts trong tình huống này. Nhưng, vì câu hỏi là làm thế nào để đảm bảo việc giải phóng bộ nhớ trong một ngữ cảnh, phương thức ClearCache() gần hơn với câu trả lời. –

+0

Có, sử dụng hay không nhiều datacontext phụ thuộc vào số lượng dữ liệu của bạn, bạn có thể tìm hiểu làm thế nào để đối phó với điều này, tôi học từ RobConery MVC Road series ... http://blog.wekeroad.com/category/mvc-storefront –

+3

InvokeMember context.GetType() ( \t "ClearCache", \t BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, \t null, bối cảnh, null);: đây là cách bạn có thể gọi ClearCache(). – Rafe

20

Một DataContext theo dõi tất cả các đối tượng đã được tìm nạp. Nó sẽ không giải phóng cho đến khi nó được thu gom rác. Ngoài ra, khi triển khai IDisposable, bạn phải gọi số Dispose hoặc sử dụng câu lệnh using.

Đây là cách đúng đắn để đi:

using(DataContext myDC = new DataContext) 
{ 
    // Do stuff 
} //DataContext is disposed 
6

Khi David chỉ ra, bạn nên vứt bỏ DataContext bằng khối sử dụng.

Dường như mối quan tâm chính của bạn là tạo và xử lý một loạt các đối tượng DataContext. Đây là cách linq2sql được thiết kế. DataContext có nghĩa là có tuổi thọ ngắn. Vì bạn đang lấy rất nhiều dữ liệu từ DB, điều đó có nghĩa là sẽ có rất nhiều việc sử dụng bộ nhớ. Bạn đang đi đúng hướng, bằng cách xử lý dữ liệu của bạn theo khối.

Đừng sợ tạo ra hàng tấn DataContexts. Chúng được thiết kế để sử dụng theo cách đó.

3

Xin cảm ơn các bạn - Tôi sẽ xem phương pháp ClearCache. Chỉ để làm rõ (cho độc giả trong tương lai), tình huống mà tôi đã nhận được bộ nhớ usuage là một cái gì đó như thế này:

using(DataContext context = new DataContext()) 
{ 
    while(true) 
    { 
     int skipAmount = 0; 
     var rows = context.tables.Select(x => x.Dept == "Dept").Skip(skipAmount).Take(100); 

     //break out of loop when out of rows 

     foreach(table t in rows) 
     { 
     //make changes to t 
     } 

     context.SubmitChanges(); 
     skipAmount += rows.Count(); 

     rows.Clear(); 
     rows = null; 

     //at this point, even though the rows have been cleared and changes have been 
     //submitted, the context is still holding onto a reference somewhere to the 
     //removed rows. So unless you create a new context, memory usuage keeps on growing 
    } 
} 
0

Tôi chỉ chạy vào một vấn đề tương tự. Trong trường hợp của tôi, đã giúp thiết lập các thuộc tính của DataContext.ObjectTrackingEnabled thành sai. Nhưng nó chỉ có tác dụng trong trường hợp lặp lại qua các hàng như sau:

using (var db = new DataContext()) 
{ 
    db.ObjectTrackingEnabled = false; 
    var documents = from d in db.GetTable<T>() 
        select d; 
    foreach (var doc in documents) 
    { 
     ... 
    } 
} 

Nếu, ví dụ, trong truy vấn sử dụng các phương pháp ToArray() hoặc ToList() - không có tác dụng

Các vấn đề liên quan