8

Tôi đang sử dụng Entity Framework CodeFirst nơi tôi đã sử dụng mối quan hệ Child Chánh sử dụng ICollection nhưDoes AsQueryable() trên ICollection thực sự làm cho thực hiện lười biếng?

public class Person 
{ 
    public string UserName { get;set} 
    public ICollection<Blog> Blogs { get; set;} 
} 

public class Blog 
{ 
    public int id { get; set; } 
    public string Subject { get; set; } 
    public string Body { get; set; } 
} 

Ok, cho đến nay tất cả mọi thứ đang làm việc ok, nhưng mối quan tâm của tôi là, bất cứ khi nào tôi muốn nhận được Blogs của một người, Tôi nhận được nó là

var thePerson = _context.Persons.Where(x => x.UserName = 'xxx').SingleOrDefault(); 
var theBlogs = thePerson.Blogs.OrderBy(id).Take(5); 

Bây giờ, tôi hiểu rằng, khi dòng được thực hiện, tất cả Blog cho người đó được tải vào bộ nhớ, sau đó sắp xếp và chọn được thực hiện từ bộ nhớ. Đó không phải là lý tưởng cho một bản ghi của người có số lượng lớn các blog. Tôi muốn biến Blog Child thành IQueryable để việc sắp xếp và chọn được thực hiện trong cơ sở dữ liệu SQL trước khi kéo vào bộ nhớ.

Tôi biết tôi có thể tuyên bố Nhật ký điện tử như IQueryable trong bối cảnh của tôi để tôi có thể truy vấn trực tiếp như

var theBlogs = _context.Blogs.Where(.....) 

nhưng đó không phải là khả thi đối với tôi do để thiết kế lựa chọn, tôi muốn tránh bất kỳ tham chiếu vòng tròn như nhiều nhất có thể do vấn đề serialization. Vì vậy, tôi không đưa ra bất kỳ tham chiếu nào về thực thể cha mẹ trong con tôi.

tôi thấy rằng, tôi có thể gọi phương thức AsQueryable() trên các blog như

var theBlogs = thePerson.Blogs.AsQueryable().OrderBy(id).Take(5); 

Trông giống như một ma thuật đối với tôi và dường như quá tốt đến mức khó tin. Vì vậy, câu hỏi của tôi. Liệu AsQueryable này có thực sự làm cho ICollection như IQueryable trong thực tế và làm cho tất cả các quá trình truy vấn trong SQL Server (tải Lazy) HOẶC nó chỉ là một diễn viên mà Blogs được nạp vào bộ nhớ như trước đây, nhưng thay đổi giao diện từ ICollection thành IQueryable?

+2

Sau này, không phải trước đây. – Enigmativity

+0

Cảm ơn - Enigmativity, do đó, sự nghi ngờ của tôi là sự thật sau đó. thật buồn. –

Trả lời

6

Vì vậy, thực tế dường như viết thuộc tính điều hướng của bạn là IQueryable<T>is not possible.

gì bạn có thể làm là thêm một tài sản chuyển hướng để Blog:

public class Blog 
{ 
    public int id { get; set; } 
    public string Subject { get; set; } 
    public string Body { get; set; } 
    public virtual Person Owner { get; set; } 
} 

Từ đó, bạn có thể truy vấn như sau vì vậy nó sẽ không nạp tất cả mọi thứ vào bộ nhớ:

var thePerson = _context.Persons.Where(x => x.UserName = 'xxx').SingleOrDefault(); 
var results = _context.Blogs.Where(z => z.Person.Name = thePerson.Name).OrderBy(id).Take(5) 

Tôi đề nghị bạn hãy thử LINQPad để xem cách LINQ được dịch sang SQL và những gì thực sự được yêu cầu từ DB.

+0

Cảm ơn bạn rất nhiều vì đã trả lời. Ok, do đó, nó có nghĩa là, ICollection cũng là một bộ nạp lười biếng như IQueryable và tôi có thể sử dụng một cách an toàn ICollection bất cứ nơi nào thay cho IQueryable nơi tôi muốn truy vấn nên diễn ra trong cơ sở dữ liệu? Về LINQPAD, tôi nghĩ rằng cung cấp cho ý tưởng therotical về bản dịch SQL là gì, nhưng có lẽ một số EntityFramework Profiler có thể giúp tốt hơn để xem những gì QUERY là actully được gửi trong cơ sở dữ liệu. Tôi không có bất kỳ Profiler Framework Entity nào, nhưng bây giờ tôi đang xem xét một số sản phẩm như thế. –

+0

Chỉ là một câu hỏi khác, vì vậy nếu câu trả lời của câu hỏi trước của tôi là CÓ, thì tôi không cần sử dụng AsQueryable() nữa cho ICollection, đúng không? –

+1

+1 để giới thiệu một công cụ giúp việc phát triển các truy vấn LINQ dễ dàng hơn. –

2

Cách tiếp cận tốt hơn được mô tả trong Ladislav's answer. Trong trường hợp của bạn:

var theBlogs = _context.Entry(thePerson) 
         .Collection(x => x.Blogs) 
         .Query() 
         .OrderBy(x => x.id) 
         .Take(5); 
Các vấn đề liên quan