8

Tôi có một phương pháp trên lớp một phần tạo ra tôi như thế này:.Skip() Take() trên Entity Framework Navigation Thuộc tính đang thực hiện SELECT * trên của tôi SQL Server

var pChildren = this.Children 
    .Skip(skipRelated) 
    .Take(takeRelated) 
    .ToList(); 

Khi tôi nhìn vào SQL Server của tôi , Tôi có thể thấy mã được tạo đang thực hiện SELECT *.* FROM Children Mã này được lấy trực tiếp từ lớp của tôi, tôi đã xác minh rằng thứ tự Bỏ qua/Thực hiện của tôi là TRƯỚC KHI .ToList của tôi.

Nếu tôi loại bỏ .ToList, dòng đó nhanh (và không có SQL được gửi đến DB của tôi), nhưng thời điểm tôi cố gắng foreach qua kết quả, tôi nhận được cùng một SQL được gửi đến DB của tôi: SELECT *.* FROM Children.

Có điều gì đặc biệt tôi cần phải làm khi sử dụng .Skip và .Take trên thuộc tính điều hướng đối tượng của tôi?

cập nhật

Tôi sẽ cố gắng để có được SQL thực tế tạo ra, Tôi hiện đang không thiết lập cho điều đó. Tôi tìm thấy cái đầu tiên bởi vì nó xuất hiện trong danh sách "truy vấn đắt tiền" của SSMS.

Chạy này:

var pChildren = this.Children 
    //.Skip(skipRelated) 
    //.Take(takeRelated) 
    .ToList(); 

lợi nhuận ~ 4.000.000 hàng và mất ~ 25 giây.

Chạy này:

var pChildren = this.Children 
    //.Skip(skipRelated) 
    .Take(takeRelated) 
    .ToList(); 

lợi nhuận ~ 4.000.000 hàng và mất ~ 25 giây.

Như tôi đã nói, tôi sẽ lấy SQL được tạo cho chúng và đặt chúng lên.

+0

SQL Những gì bạn đã mong đợi đoạn mã này để tạo ra? – cdhowie

+0

Tôi đã hy vọng cho một cái gì đó giống như 'SELECT TOP 10 TỪ trẻ em WHERE ParentID = @ idOfParentEntity' (Tôi quên cách EF xử lý .Sip, nhưng tôi đã đọc nó là nghĩa vụ phải. Nếu tôi thực hiện truy vấn này đối với bối cảnh của tôi trực tiếp nó xuất hiện để giới hạn dữ liệu được trả về một "trang" cụ thể) – Nate

+0

Sự hiện diện của '.Skip()' ngăn cản việc sử dụng 'TOP'. Trừ khi bạn mong đợi nó để tổng hợp 'skipRelated' và' takeRelated' và sử dụng nó như tham số 'TOP' ... có thể là một tối ưu hóa, nhưng nó cũng có thể không có tác động đến hiệu suất. – cdhowie

Trả lời

7

Vấn đề là bạn đang thực hiện một truy vấn LINQ-to-Object khi bạn truy vấn một bộ sưu tập con như thế. EF sẽ tải toàn bộ bộ sưu tập và thực hiện truy vấn trong bộ nhớ.

Nếu bạn đang sử dụng EF 4 bạn có thể truy vấn như thế này

var pChildren = this.Children.CreateSourceQuery() 
       .OrderBy(/* */).Skip(skipRelated).Take(takeRelated); 

Trong EF 4,1

var pChildren = context.Entry(this) 
        .Collection(e => e.Children) 
        .Query() 
        .OrderBy(/* */).Skip(skipRelated).Take(takeRelated) 
        .Load(); 
+0

Chính xác những gì tôi cần. Tôi đang sử dụng EF4.1 nhưng truy vấn đầu tiên hoạt động tốt hơn cho tôi, vì tôi không có quyền truy cập vào ngữ cảnh của mình từ phương thức cụ thể này. – Nate

1

Có trợ giúp không nếu bạn gọi Skip do kết quả của Take? ví dụ:

table.Take(takeCount+skipCount).Skip(skipCount).ToList() 

Ngoài ra, xem

+5

mất trước khi bỏ qua không có ý nghĩa – vittore

+1

@vittore: Chắc chắn rồi. Nếu bạn muốn các bản ghi 51-100, thay vì lấy một triệu cho khách hàng, bỏ đi 50, giữ 50, và vứt bỏ phần còn lại, bạn có thể lấy 100 cho khách hàng và vứt bỏ 50. –

+0

@BenVoigt Trong khi đó là sự thật, nó không giúp ích gì nhiều cho đến cuối trang. – Nate

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