2012-04-11 34 views
42

Khi sử dụng DbContext trong kịch bản cơ sở dữ liệu đầu tiên, tôi phát hiện ra rằng việc thêm và xóa các thực thể là rất chậm so với ObjectContext. Nếu thêm 2000 thực thể và lưu các thay đổi ở cuối, DbContext chậm hơn 3 đến 5 lần so với ObjectContext (btw .: Tôi biết rằng việc thêm một số lượng lớn các thực thể sẽ tốt hơn khi sử dụng SqlBulkCopy nhưng đó không phải là điểm). Nếu lưu thay đổi sau mỗi lần bổ sung, DbContext vẫn chậm hơn gần gấp hai lần. Khi nói đến xóa nó thậm chí còn tồi tệ hơn: Khi tiết kiệm ở cuối của tất cả các loại bỏ thực thể, DbContext là khoảng 18 lần chậm hơn so với ObjectContext.DbContext rất chậm khi thêm và xóa

Tôi đã sử dụng ứng dụng thử nghiệm phát triển cao mà tôi sử dụng để so sánh các công nghệ truy cập cơ sở dữ liệu và ứng dụng bảng điều khiển nhỏ để kiểm tra kỹ. Cả hai cho thấy kết quả xấu cho việc thêm và xóa các thực thể bằng DbContext. Đây là kết quả của ứng dụng giao diện điều khiển:

Inserting 2000 entities via DbContext saving changes at the end: 2164ms 
Inserting 2000 entities via ObjectContext saving changes at the end: 457ms 
Inserting 2000 entities via DbContext saving changes after each object addition: 8420ms 
Inserting 2000 entities via ObjectContext saving changes after each object adding: 4857ms 
Inserting 2000 entities via DbContext using a new DbContext for each object addition: 4018ms 
Deleting 2000 entities via DbContext saving changes at the end: 4794ms 
Deleting 2000 entities via ObjectContext saving changes at the end: 261ms 
Deleting 2000 entities via DbContext saving changes after each object deletion: 25536ms 
Deleting 2000 entities via ObjectContext saving changes after each object deletion: 2110ms 

Tôi đã thử sử dụng EF 4.3 trong VC 2010 và EF 5.0 Beta 2 trong VS 11 với cùng kết quả. Tôi đã sử dụng các mẫu T4 được cung cấp bởi "Máy phát điện Entity của EF 4.x cho C#", "Máy phát điện EF 4.x DbContext cho C#" và "Máy phát điện DbContext EF 5.x cho C#".

Điều gì có thể sai? Theo kết quả kiểm tra, tôi sẽ không bao giờ sử dụng DbContext trong một ứng dụng có thêm hoặc xóa các thực thể (điều làm cho DbContext tiếc là không thể sử dụng được cho tôi).

tôi đặt các ứng dụng thử nghiệm giao diện điều khiển trên máy chủ web của tôi: EF 4.3 DbContext Test, EF 5.0 DbContext Test

Bất kỳ ý tưởng/chỉnh sửa được đánh giá cao.

+0

Hai tham chiếu ngoài Ladislavs trả lời: http://stackoverflow.com/questions/5943394/why-is-inserting-entities-in-ef-4-1-so-slow-compared-to-objectcontext/5943699 # 5943699 và http://stackoverflow.com/questions/5940225/fastest-way-of-inserting-in-entity-framework/5942176#5942176 – Slauma

Trả lời

86

Cố gắng thêm video này vào kiểm tra DbContext của bạn:

dbContext.Configuration.AutoDetectChangesEnabled = false; 

// Now do all your changes 

dbContext.ChangeTracker.DetectChanges(); 
dbContext.SaveChanges(); 

và cố gắng chạy thử nghiệm của bạn một lần nữa.

Có một số thay đổi về kiến ​​trúc trong API DbContext kiểm tra các thay đổi trong thực thể mỗi khi bạn Add, Attach hoặc Delete bất kỳ nội dung gì từ ngữ cảnh. Trong API ObjectContext, phát hiện này chỉ chạy khi bạn kích hoạt SaveChanges. Đó là giải pháp tốt hơn cho hầu hết các kịch bản phổ biến nhưng nó đòi hỏi xử lý đặc biệt để xử lý dữ liệu hàng loạt.

+1

Cảm ơn Ladislav. Đó thực sự là nguyên nhân gây ra vấn đề hiệu suất khi thêm/xóa nhiều thực thể và lưu thay đổi ở cuối. Sau khi thiết lập AutoDetectChangesEnabled thành false, kết quả gần như giống với ObjectContext.Nhưng vẫn còn chèn đơn và đặc biệt là xóa một lần duy nhất sau đó một SaveChanges là chậm hơn so với ObjectContext, ngay cả khi tôi đặt AutoDetectChangesEnabled thành false và gọi DetectChanges trước SaveChanges. Việc xóa 2000 thực thể vẫn mất khoảng 17 giây khi sử dụng DbContext trong khi –

+0

... chỉ mất khoảng 2,1 giây khi sử dụng ObjectContext. Tôi cho rằng đó là vì những thay đổi này trong theo dõi thay đổi. Nhân tiện: Bạn có thể giải thích tại sao việc kiểm tra thay đổi mỗi khi thêm, đính kèm hoặc xóa là giải pháp tốt hơn cho hầu hết các trường hợp phổ biến? –

+3

@ JürgenBayer: Tôi đã sao chép sự khác biệt hiệu suất lớn cho 'DeleteObject/Remove' mà bạn đã mô tả trong nhận xét của mình. Sự khác biệt sẽ biến mất nếu bạn xóa 'DetectChanges' khỏi mã (điều này không thực sự cần thiết nếu bạn chỉ thêm và xóa các thực thể). Tuy nhiên, sự hiểu biết của tôi là 'ObjectContext.SaveChanges()' gọi 'DetectChanges' nội bộ, trong khi' DbContext.SaveChanges() 'không khi' AutoDetectChanges' bị vô hiệu hóa. Vì vậy, gọi 'DetectChanges' +' DbContext.SaveChanges() '(với AutoDetectChanges bị vô hiệu hóa) nên giống như gọi' ObjectContext.SaveChanges() '- theo lý thuyết. – Slauma

11

Trong EF6, bạn hiện có thể sử dụng AddRangeRemoveRange trên DbSet.

Từ các tài liệu vào các liên kết:

Lưu ý rằng nếu AutoDetectChangesEnabled được thiết lập là true (đó là mặc định), sau đó DetectChanges sẽ được gọi là một lần trước {thêm, xoá} bất kỳ thực thể và sẽ không được gọi lại. Điều này có nghĩa là trong một số trường hợp {Add, Remove} Phạm vi có thể hoạt động tốt hơn đáng kể so với gọi {Add, Remove} nhiều lần.