2009-02-10 35 views
7

Tôi đang cố gắng làm những gì tôi nghĩ là một cái gì đó đơn giản, nhưng tôi nghi ngờ tôi chỉ đơn giản là quá n00b để biết rằng tôi có thể làm điều gì sai. Tôi có một sự trở lại truy vấn LINQ:Đang cố gắng thay đổi các thuộc tính của một bộ sưu tập IQueryable

IQueryable<CWords> Result 

đâu CWords là một lớp I được xác định như sau:

public class CWords 
{ 
    public CWords(){} 
    public string _column1{ get; set; } 
    public float _column2{ get; set; } 

    public void fixData(){} 
} 

trong mã của tôi, tôi đang cố gắng để modidy lĩnh vực _column2 cho mỗi thành viên của quả. Tôi đã thử:

foreach (CWords item in Result) 
{ 
    item.fixData(); 
} 

Nhưng tất nhiên điều đó không hiệu quả. mục không nằm trong phạm vi thích hợp, vì vậy bất kỳ thay đổi nào tôi đã thực hiện trong fixData không được đưa vào Kết quả.

Bcause bạn có thể không chỉ thành IQueryable, sửa chữa của tôi cho điều này là phải làm như sau:

var items = goodWords.ToList(); 

for (int i = 0; i < items.Count(); i++) 
    { 
    items[i].fixData(); 
    } 

Đó có phải là cách đúng đắn để làm điều này?

Trả lời

13

Brandon, đây là sai lầm bình thường khi sử dụng LINQ. Xem, các IQueryable trở về từ LINQ không thực sự chứa các mục của bạn, đó là lý do tại sao bạn không thể lập chỉ mục vào nó. Nó chỉ có đủ thông tin để thực hiện truy vấn khi bạn thực sự yêu cầu các mục. Điều này được gọi là "deferred execution", vì truy vấn không được thực hiện khi bạn select, nhưng sau đó, khi bạn liệt kê kết quả. Bạn có thể tìm kiếm "thực thi trì hoãn LINQ" và tìm thấy rất nhiều người đang cố gắng giải thích cách hoạt động của nó.

Khi bạn thực hiện foreach, truy vấn sẽ chạy và bạn đang gọi hàm fixData() trên mỗi mục, giống như bạn dự định. Tuy nhiên, khi bạn truy cập lại IQueryable, bạn sẽ thực hiện truy vấn lần thứ hai và (tùy thuộc vào nhà cung cấp LINQ bạn đang sử dụng), bạn có thể mang lại các mục không sửa đổi ban đầu lần thứ hai.

Bằng cách gọi ToList() trên IQueryable, bạn đang tạo Danh sách trong bộ nhớ với tất cả kết quả của truy vấn. Bây giờ bạn có thể lập chỉ mục vào danh sách này và truy cập tất cả những gì bạn muốn mà không cần thực hiện lại truy vấn. Nếu bạn ổn với việc có tất cả các mục trong bộ nhớ (tập hợp kết quả nhỏ), thì sử dụng ToList() có thể là một giải pháp tốt cho bạn.

@PaulG, bạn nói đúng rằng anh ấy có thể sử dụng foreach thay vì for, nhưng anh ấy nên lưu tham chiếu đến danh sách hoặc người khác anh ấy đúng nơi anh ấy bắt đầu (với IQueryable).

var items = goodWords.ToList(); 

foreach (var item in items) 
{ 
    item.fixData(); 
} 
0

Tôi tin rằng goodWords của bạn là IQueryable<CWords> loại?

Vậy tại sao không thích điều này?

foreach (CWords item in goodWords.ToList()) 
{ 
    item.fixData(); 
} 
Các vấn đề liên quan