2012-02-17 34 views
5

Tôi có một phương pháp cung cấp trong Dal:Lợi nhuận hồ sơ cơ sở dữ liệu lợi nhuận sử dụng LINQToSql?

public IEnumerable<RecordType> GetRecords() 
{ 
    using (LinqDataContext context = new LinqDataContext()) 
    { 
     var records = context.RecordTable; 

     foreach (RecordType record in records) 
     { 
      yield return record; 
     } 
    } 
} 

Phương pháp của người tiêu dùng sử dụng các bản ghi trong một vòng lặp foreach. Bằng cách này tôi muốn tiết kiệm sử dụng bộ nhớ bằng cách không lưu trữ tất cả các bản ghi từ RecordTable, vì LinqToSql sử dụng một DataReader phía sau khung cảnh.

Tôi có hai câu hỏi về tình huống này mặc dù:

  1. Is that true rằng năng suất-trở về trên tiết kiệm nguồn lực và hoạt động nhanh hơn so với bộ nhớ đệm toàn bộ hồ sơ đến một mảng (.ToArray())?

  2. sẽ kết nối dữ liệu được tự động đóng lại đúng cách (Ý tôi là báo cáo kết quả using) nếu một lỗi sẽ xảy ra bên trong foreach vòng lặp của phương pháp tiêu thụ HOẶC nếu phương pháp tiêu thụ sẽ phá vỡ foreach vòng ở giữa (như tìm thấy một yêu cầu hồ sơ và break)?

Trả lời

3

Trong trường hợp thực hiện một truy vấn cơ bản, nó có thể làm việc theo cách đó (chắc chắn là có thể) - tuy nhiên, trong trường hợp truy vấn một naked Table<T>, có thể là là tất cả các bộ đệm đầu tiên; bạn có thể thử truy vấn đếm trong khi lặp lại hoặc chạy một dấu vết. Trong trường hợp này, tôi nghi ngờ nó sẽ đệm trước.

Đóng lại: điều đó cũng phụ thuộc: p Nếu ai đó đang sử dụng foreach, thì có: từ foreach phân phối rõ ràng trình lặp qua finally. Tuy nhiên! Nó không được đảm bảo nếu ai đó, ví dụ (rất nghịch ngợm và lỏng lẻo):

var iter = yourData.GetEnumerator(); 
if(iter.MoveNext()) { 
    Console.WriteLine(iter.Current.Name); // first record of, say, 20 
} 
// and don't dispose the iterator == bad 

sau đó kể từ khi iterator không một: nhận thanh lý khoản, b: giảm tốc, và c: không sụp đổ, nó sẽ không tắt đúng cách (bất kỳ điều kiện nào trong số 3 điều kiện này sẽ đóng đúng cách). Nhấn mạnh: đây là một trường hợp bệnh lý: thông thường nó là hợp lý an toàn để nói "nó sẽ đóng, có".

Nếu bạn muốn đảm bảo không đệm, lưu ý rằng "đoan trang" có đó, nếu bạn thiết lập buffered-false:

IEnumerable<Customer> customers = connection.Query<Customer>(
     "select * from Customer", buffered: false); 

(nó cũng có thể xử lý các thông số vv)

3

1) yield sẽ không nhất thiết phải nhanh hơn để có được tất cả các giá trị, nhưng nó sẽ cho phép mã để bắt đầu xử lý kết quả trước khi cơ sở dữ liệu đã trở lại tất cả các kết quả. Tức là, sản lượng trả về kết quả đầu tiên ngay lập tức nó xuất hiện, trong khi ToArray() cần phải đợi cho tất cả các kết quả hiển thị trước khi trở về. Tất nhiên, nếu các nhà cung cấp cơ bản trả về tất cả các kết quả cùng một lúc do đệm hoặc các lý do khác, điều này có thể không tạo sự khác biệt.

2) Có, using sẽ định đoạt của LinqDataContext dù bạn thoát khỏi khối sử dụng (ngoại lệ/khứ hồi/nghỉ/...)

+1

Thực ra, 2 là "miễn là người gọi cư xử đúng cách" - nó không hoàn toàn là "được đảm bảo" vì hầu hết 'sử dụng' là –

+0

@MarcGravell Tôi giả sử bạn đang nói về không (đúng) liệt kê toàn bộ Enumerable, hoặc tôi thiếu cái gì khác? –

+0

có, di chuyển trình vòng lặp theo cách thủ công và thực hiện không chính xác. Nó không phải là một vấn đề khi sử dụng 'foreach', mà hầu hết mọi người sane sẽ sử dụng. –

2
  1. Các trình lặp sẽ được đánh giá một cách lười biếng. Nó sẽ kéo mục đầu tiên và sau đó "mang lại" nó cho người tiêu dùng của nó.Tác động hiệu suất sẽ phụ thuộc vào cách LinqDataContext được triển khai (nó có thể lưu vào bộ nhớ cache nội bộ). Sử dụng ToArray(), hoặc ToList(), sẽ buộc tất cả các phần tử ra khỏi LinqDataContext trước khi tiếp tục. Do đó, việc sử dụng ToArray() sẽ làm cho bạn không mang lại kết quả gì cho đến khi LinqDataContext đã trả về mọi phần tử. Cho dù đó là tối ưu hay không, là tùy thuộc vào bạn.
  2. Có, "đang sử dụng" sẽ được thực thi đúng cách.
Các vấn đề liên quan