2010-09-06 34 views
239

Gần đây tôi đã bắt đầu sử dụng Entity Framework 4.0 trong ứng dụng .NET 4.0 của mình và tò mò về một số điều liên quan đến tổng hợp.Khuôn khổ thực thể và kết nối tổng hợp

  1. Kết nối tổng hợp như tôi biết được quản lý bởi nhà cung cấp dữ liệu ADO.NET, trong trường hợp của tôi là của máy chủ MS SQL. Điều này có áp dụng khi bạn khởi tạo ngữ cảnh thực thể mới (ObjectContext), tức là không tham số new MyDatabaseModelEntities()?

  2. Những ưu điểm và nhược điểm của a) tạo ngữ cảnh thực thể toàn cầu cho ứng dụng (ví dụ: một trường hợp tĩnh) hoặc b) tạo và hiển thị ngữ cảnh thực thể cho từng hoạt động/phương thức đã cho, với khối using.

  3. Bất kỳ đề xuất nào khác, phương pháp hay nhất hoặc phương pháp tiếp cận chung cho một số trường hợp nhất định mà tôi nên biết?

Trả lời

347
  1. Kết nối tổng hợp được xử lý như trong bất kỳ ứng dụng ADO.NET nào khác. Kết nối thực thể vẫn sử dụng kết nối cơ sở dữ liệu truyền thống với chuỗi kết nối truyền thống. Tôi tin rằng bạn có thể tắt ghép nối kết nối trong chuỗi kết nối nếu bạn không muốn sử dụng nó. (đọc thêm về SQL Server Connection Pooling (ADO.NET))
  2. Không bao giờ sử dụng ngữ cảnh chung. ObjectContext nội bộ thực hiện một số mẫu bao gồm Bản đồ nhận dạng và Đơn vị công việc. Tác động của việc sử dụng ngữ cảnh toàn cầu là khác nhau đối với mỗi loại ứng dụng.
  3. Đối với các ứng dụng web, hãy sử dụng ngữ cảnh đơn theo yêu cầu. Đối với các dịch vụ web, hãy sử dụng ngữ cảnh đơn cho mỗi cuộc gọi. Trong ứng dụng WinForms hoặc WPF, hãy sử dụng ngữ cảnh đơn trên mỗi biểu mẫu hoặc cho mỗi người trình bày. Có thể có một số yêu cầu đặc biệt mà sẽ không cho phép sử dụng phương pháp này nhưng trong hầu hết trường hợp, điều này là đủ.

Nếu bạn muốn biết tác động nào có bối cảnh đối tượng đơn cho ứng dụng WPF/WinForm, hãy kiểm tra điều này article. Đó là về phiên NHibernate nhưng ý tưởng là như nhau.

Edit:

Khi bạn sử dụng EF nó bằng cách tải mặc định mỗi thực thể duy nhất một lần mỗi ngữ cảnh. Truy vấn đầu tiên tạo ra instace thực thể và lưu trữ nó trong nội bộ. Bất kỳ truy vấn tiếp theo nào yêu cầu thực thể có cùng khóa trả về phiên bản được lưu trữ này. Nếu các giá trị trong kho dữ liệu thay đổi, bạn vẫn nhận được thực thể với các giá trị từ truy vấn ban đầu. Điều này được gọi là Mẫu bản đồ nhận dạng. Bạn có thể buộc bối cảnh đối tượng tải lại thực thể nhưng nó sẽ tải lại một cá thể được chia sẻ duy nhất.

Bất kỳ thay đổi nào được thực hiện cho đối tượng không được duy trì cho đến khi bạn gọi SaveChanges trong ngữ cảnh. Bạn có thể thực hiện thay đổi trong nhiều thực thể và lưu trữ chúng cùng một lúc.Điều này được gọi là Đơn vị công việc mẫu. Bạn không thể chọn một cách chọn lọc đối tượng được đính kèm đã sửa đổi mà bạn muốn lưu.

Kết hợp hai mẫu này và bạn sẽ thấy một số hiệu ứng thú vị. Bạn chỉ có một thể hiện của thực thể cho toàn bộ ứng dụng. Bất kỳ thay đổi nào đối với thực thể ảnh hưởng đến toàn bộ ứng dụng ngay cả khi các thay đổi chưa được duy trì (cam kết). Trong hầu hết thời gian này không phải là những gì bạn muốn. Giả sử bạn có một biểu mẫu chỉnh sửa trong ứng dụng WPF. Bạn đang làm việc với thực thể và bạn quyết định hủy chỉnh sửa phức tạp (thay đổi giá trị, thêm các thực thể liên quan, xóa các thực thể liên quan khác, v.v.). Nhưng thực thể đã được sửa đổi trong ngữ cảnh được chia sẻ. Bạn sẽ làm gì? Gợi ý: Tôi không biết về bất kỳ CancelChanges hoặc UndoChanges trên ObjectContext.

Tôi nghĩ chúng ta không phải thảo luận về kịch bản máy chủ. Chỉ cần chia sẻ một thực thể duy nhất trong số nhiều yêu cầu HTTP hoặc các cuộc gọi dịch vụ web làm cho ứng dụng của bạn vô dụng. Mọi yêu cầu chỉ có thể kích hoạt SaveChanges và lưu một phần dữ liệu từ một yêu cầu khác bởi vì bạn đang chia sẻ một đơn vị công việc trong số tất cả chúng. Điều này cũng sẽ có một vấn đề khác - ngữ cảnh và bất kỳ thao tác nào với các thực thể trong ngữ cảnh hoặc kết nối cơ sở dữ liệu được sử dụng bởi ngữ cảnh không phải là luồng an toàn.

Ngay cả đối với ứng dụng chỉ đọc, ngữ cảnh chung không phải là lựa chọn tốt vì bạn có thể muốn dữ liệu mới mỗi khi bạn truy vấn ứng dụng.

+0

Cảm ơn bạn đã trả lời. Có lẽ bạn có thể giải thích tại sao việc sử dụng một bối cảnh toàn cục duy nhất là xấu? Nó làm cho truy cập song song khó khăn hơn, chắc chắn, nhưng những gì khác ...? – Noldorin

+0

Ok, giờ đây rõ ràng hơn rất nhiều, cảm ơn bạn. Chỉ cần xác nhận, mặc dù bối cảnh toàn cầu chưa bao giờ thực sự thích hợp, một bối cảnh duy nhất cho một "hộp thoại chỉnh sửa" hoặc như vậy có thể là đúng cách? Trong các tình huống khác, như các dịch vụ web và ASP.NET, các ngữ cảnh bên trong các phương thức chỉ có ý nghĩa hơn. Về chính xác? – Noldorin

+0

Tôi đã tư vấn của bạn và loại bỏ các singelton. Bây giờ tôi nhận được một lỗi khác: http://stackoverflow.com/questions/14795899/an-entity-object-cannot-be-referenced-by-multiple-instances-of-ientitychangetrac –

61

Theo Daniel Simmons:

Create a new ObjectContext instance in a Using statement for each service method so that it is disposed of before the method returns. This step is critical for scalability of your service. It makes sure that database connections are not kept open across service calls and that temporary state used by a particular operation is garbage collected when that operation is over. The Entity Framework automatically caches metadata and other information it needs in the app domain, and ADO.NET pools database connections, so re-creating the context each time is a quick operation.

Đây là từ bài viết toàn diện của mình ở đây:

http://msdn.microsoft.com/en-us/magazine/ee335715.aspx

Tôi tin rằng lời khuyên này kéo dài đến các yêu cầu HTTP, như vậy sẽ có giá trị ASP.NET. Một ứng dụng stateful, fat-client như một ứng dụng WPF có thể là trường hợp duy nhất cho một bối cảnh "được chia sẻ".

+0

Cảm ơn, đó là một trích dẫn rất có nhiều thông tin ở đó. Tuy nhiên, tôi vẫn tự hỏi liệu một bối cảnh chia sẻ (toàn cầu) sẽ được appropiate ngay cả đối với một ứng dụng khách WPF hay như vậy. Có * lợi thế nào * ngay cả trong trường hợp này không? – Noldorin

+0

Sẽ không có lợi thế nào cho bối cảnh toàn cầu trong một ứng dụng WPF, nhưng có lẽ cũng sẽ không gây thiệt hại đáng kể. Nếu bạn thực hiện một bối cảnh chung, bạn có thể phải thực hiện một số quản lý thủ công các kết nối cơ sở dữ liệu (kết thúc rõ ràng kết nối) trong các trường hợp yêu cầu cao. –

+1

Phải; về cơ bản tôi có thể không bao giờ thực sự đi sai bằng cách sử dụng nhiều bối cảnh tạm thời (cho tôi biết kết nối tổng hợp đang xảy ra)? ... Nếu bạn đang sử dụng một bối cảnh toàn cục, không thể kết nối trong lý thuyết rơi vào một thời điểm ngẫu nhiên? – Noldorin

2

Mã dưới đây đã giúp đối tượng của tôi được làm mới với các giá trị cơ sở dữ liệu mới. Lệnh nhập cảnh (đối tượng) .Reload() lực lượng đối tượng để thu hồi cơ sở dữ liệu giá trị

GM_MEMBERS member = DatabaseObjectContext.GM_MEMBERS.FirstOrDefault(p => p.Username == username && p.ApplicationName == this.ApplicationName); 
DatabaseObjectContext.Entry(member).Reload(); 
+0

cũng như điều này cho các bộ sưu tập (mã VB): 'CType (myContext, IObjectContextAdapter) .ObjectContext.Refresh (RefreshMode.StoreWins, myCustomers)' –

6

Accoriding để EF6 (4,5 cũng) tài liệu: https://msdn.microsoft.com/en-us/data/hh949853#9

9,3 Bối cảnh theo yêu cầu

ngữ cảnh của Entity Framework có nghĩa là được sử dụng như các trường hợp ngắn ngủi để cung cấp trải nghiệm hiệu suất tối ưu nhất. Các bối cảnh được dự kiến ​​sẽ tồn tại trong thời gian ngắn và bị loại bỏ, và như vậy đã được thực hiện rất nhẹ và tái sử dụng siêu dữ liệu bất cứ khi nào có thể. Trong các tình huống trên web, điều quan trọng là phải ghi nhớ điều này và không có ngữ cảnh nhiều hơn thời lượng của một yêu cầu. Tương tự như vậy, trong các tình huống không phải web, bối cảnh phải được loại bỏ dựa trên sự hiểu biết của bạn về các mức bộ nhớ đệm khác nhau trong Khuôn khổ thực thể. Nói chung, người ta nên tránh có một bối cảnh ngữ cảnh trong suốt vòng đời của ứng dụng, cũng như ngữ cảnh cho mỗi chủ đề và ngữ cảnh tĩnh.

+0

Tôi biết câu trả lời này đã ở đây một thời gian, nhưng tôi phải nói điều này đã cứu tôi một tấn nhức đầu. Giữ lỗi "Kết nối gộp" khi sử dụng EF với Oracle và không thể hiểu tại sao. Tôi đã đặt dbContext lên như là một biến lớp, khởi tạo nó lúc tạo. Thay đổi nó để tạo ra bối cảnh khi cần thiết cố định tất cả các căn bệnh của thế giới của tôi. Cảm ơn bạn! – Fletchius

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