2013-03-11 9 views
9

Tôi đã đọc một vài bài báo (article1, article2) về Khung thực thể mà nó gọi là Phát hiện nhiều lần, điều này làm cho nó rất chậm khi làm việc với một lượng lớn dữ liệu.Mã EF Đầu tiên: tốt để gọi DetectChanges ngay trước SaveChanges?

Tôi có thể, ví dụ: vô hiệu hóa autoDetectChanges khi tôi khởi tạo ngữ cảnh và chỉ cần gọi DetectChanges() trước khi gọi .SaveChanges()?

Ngữ cảnh có nhận ra các thực thể được chèn/thay đổi/đã xóa không?

var _dbContext = new ProjectContext(); 
_dbContext.Configuration.AutoDetectChangesEnabled = false; 

// add/edit/delete entities 

_dbContext.ChangeTracker.DetectChanges(); 
_dbContext.SaveChanges(); 

Phương pháp này có hiệu quả không? hoặc nó có thể tạo ra các lỗi ẩn?

+0

không chắc chắn 100% nếu nó làm bất kỳ điều gì lạ trong nền, nhưng tôi đã sử dụng một cách tiếp cận tương tự mà không tìm thấy bất kỳ tác dụng phụ xấu – Thewads

Trả lời

16

Arthur Vickers xác định quy tắc khi DetectChanges không cần phải được gọi (thậm chí không trước SaveChanges) in this blog post:

Không gọi mã EF sẽ rời khỏi bối cảnh trong một tiểu bang nơi DetectChanges cần phải được gọi nếu nó không cần phải được gọi là trước đây.

Về ThêmXóa đây là những "mã EF" phương pháp vì bạn gọi Add hoặc Delete hoặc bạn thiết lập trạng thái của context.Entry(entity).State để Added hay Deleted. Vì vậy, nếu bạn chỉ cần lặp qua một loạt các entites và thêm hoặc xóa chúng thì bạn không cần phải gọi DetectChanges cả.

Liên quan đến Chỉnh sửa đó là, tôi tin rằng, một chút tinh tế hơn. Khi bạn cập nhật các đối tượng bằng cách sử dụng một trong hai ...

context.Entry(entity).CurrentValues.SetValues(someObject); 

... hoặc bằng cách sử dụng API tài sản của DbContext ...

context.Entry(entity).Property(e => e.SomeProperty).CurrentValue = someValue; 

... sau đó bạn không cần phải DetectChanges (thậm chí không phải trước SaveChanges) hoặc bởi vì đây là một lần nữa gọi vào "mã EF".

Nếu bạn chỉ cần thay đổi giá trị tài sản của một thực thể giống như ...

entity.SomeProperty = someValue; 

... thì quy tắc thứ hai in the same blog post liên kết ở trên được áp dụng:

Bất cứ lúc nào mà không EF thay đổi mã bất kỳ giá trị tài sản nào của một thực thể hoặc đối tượng phức tạp thì có thể cần phải gọi DetectChanges.

Và tôi nghĩ rằng bạn cần trên thực tế chỉ có một cuộc gọi duy nhất để DetectChanges trước SaveChangesnếu bạn chỉ cần vòng lặp thông qua một số đối tượng, tải chúng vào hoặc đính kèm chúng vào bối cảnh và thay đổi một số (vô hướng và phức tạp) giá trị tài sản .

Nếu bạn làm những thứ phức tạp hơn (có thể thay đổi mối quan hệ? Hoặc cái gì khác?) Cách tiếp cận của bạn có thể không an toàn nữa vì

  1. AutoDetectChanges sẽ không được thực hiện trong cách thức mà nó là gì và gọi nhiều phương pháp EF nếu nó sẽ là chỉ cần một lần ngay trước khi SaveChanges

  2. nó được đề cập in the same blog post một lần nữa rằng

    Nếu mã làm thay đổi thay đổi các thuộc tính của các đối tượng thay vì chỉ gọi Add or Đính kèm, sau đó, bởi Quy tắc 2, DetectChanges sẽ cần phải được gọi, ít nhất là một phần của SaveChanges và có thể cũng trước sau đó.

    (Nêu bật từ tôi)

Đáng tiếc là tôi không biết một ví dụ về mã mà sẽ hiển thị khi gọi DetectChanges ở những giai đoạn sớm hơn ngay trước SaveChanges là cần thiết. Nhưng vì điểm 1 ở trên tôi chắc chắn rằng các ví dụ như vậy tồn tại.

+0

Đó là một bài viết tuyệt vời, cảm ơn bạn. Nhưng tôi là một chút không rõ ràng (xin lỗi cho điều này): 1. Tại sao EF cần phải gọi DetectChanges rất nhiều lần khi nó chỉ có thể gọi DetectChanges trước khi thực sự tiết kiệm vào cơ sở dữ liệu? 2. Tôi đang sử dụng các đối tượng 'POCO' với các thuộc tính bình thường (không được đánh dấu bằng' virtual'). Khi tôi thay đổi các giá trị thuộc tính đối tượng, EF có gọi DetectChanges() âm thầm không? – Catalin

+0

@RaraituL: Đến điểm 1: Tôi không biết. Đó là những gì tôi muốn nói với câu cuối cùng của tôi. Đến điểm 2: Số 'DetectChanges' được gọi sau trong' SaveChanges' và một loạt các phương thức EF khác, không phải khi bạn gán giá trị thuộc tính. 'DetectChanges' so sánh sau đó các giá trị thuộc tính hiện tại với các giá trị ban đầu (được lưu trữ dưới dạng" ảnh chụp nhanh "trong ngữ cảnh đối tượng) và nếu các giá trị thay đổi các thuộc tính sẽ được đánh dấu là đã sửa đổi. Nó được gọi là "theo dõi thay đổi dựa trên ảnh chụp nhanh". – Slauma

-2

Một trong những vấn đề chính có thể được giải quyết bằng DetectChanges là lưu trữ dữ liệu trong EF khi chúng tôi có mối quan hệ ManyToManyAutoDetectChanges=false.