Entity Framework với các hệ thống lớn - làm thế nào để phân chia mô hình?


50

Tôi đang làm việc với cơ sở dữ liệu SQL Server với hơn 1000 bảng, vài trăm khung nhìn khác và hàng nghìn thủ tục được lưu trữ. Chúng tôi đang tìm cách bắt đầu sử dụng Entity Framework cho các dự án mới hơn của chúng tôi và chúng tôi đang thực hiện chiến lược của mình để thực hiện điều đó. Điều tôi gác máy là cách tốt nhất để chia các bảng thành các mô hình khác nhau (EDMX hoặc DbContext nếu chúng ta đi mã trước). Tôi có thể nghĩ ra một vài chiến lược ngay lập tức:

  • Phân chia theo lược đồ
    Chúng ta có các bảng được phân chia có lẽ là một tá lược đồ. Chúng ta có thể làm một mô hình cho mỗi lược đồ. Tuy nhiên, điều này không hoàn hảo vì dbo vẫn rất lớn, với hơn 500 bảng / lượt xem. Một vấn đề khác là một số đơn vị công việc nhất định sẽ phải thực hiện các giao dịch trải rộng trên nhiều mô hình, điều này làm tăng thêm sự phức tạp, mặc dù tôi cho rằng EF thực hiện điều này khá đơn giản.
  • Chia theo ý định
    Thay vì lo lắng về lược đồ, hãy phân chia các mô hình theo ý định. Vì vậy, chúng tôi sẽ có các mô hình khác nhau cho từng ứng dụng, dự án hoặc mô-đun hoặc màn hình, tùy thuộc vào mức độ chi tiết mà chúng tôi muốn nhận. Vấn đề tôi thấy với điều này là có một số bảng nhất định chắc chắn phải được sử dụng trong mọi trường hợp, chẳng hạn như Người dùng hoặc AuditHistory. Chúng ta có thêm chúng vào mỗi mô hình (vi phạm DRY tôi nghĩ) hay là những mô hình trong một mô hình riêng biệt được sử dụng bởi mọi dự án?
  • Đừng phân chia tất cả - một mô hình khổng lồ
    Điều này rõ ràng đơn giản từ góc độ phát triển nhưng từ nghiên cứu và trực giác của tôi, dường như nó có thể thực hiện khủng khiếp, cả về thời gian thiết kế, thời gian biên dịch và có thể là thời gian chạy.

Thực tiễn tốt nhất để sử dụng EF đối với cơ sở dữ liệu lớn như vậy là gì? Cụ thể những chiến lược nào mà mọi người sử dụng trong việc thiết kế các mô hình chống lại khối lượng đối tượng DB này? Có những lựa chọn mà tôi không nghĩ về công việc đó tốt hơn những gì tôi có ở trên không?

Ngoài ra, đây có phải là vấn đề trong các ORM khác như NHibernate không? Nếu vậy họ có đưa ra giải pháp nào tốt hơn EF không?


"Phải thực hiện các giao dịch trải rộng trên nhiều mô hình, điều này làm tăng thêm độ phức tạp" Chỉ cần lưu ý ở đây là bạn sẽ cần bật Điều phối viên giao dịch phân tán của Microsoft. Một khi bạn đã có và chạy nó, thật đơn giản để thực hiện những gì bạn nói.
Tjaart

@Tjaart cảm ơn. Tôi đã sử dụng MS DTC trước đây và mặc dù nó khá đơn giản, nhưng nó lại làm tăng thêm sự phức tạp ngoài một DB txn đơn giản vì vậy tôi muốn tránh nó bất cứ khi nào có thể.
RationalGeek

2
4 năm sau, bạn đã quyết định những gì và bây giờ bạn sẽ đề nghị gì?
Rory

Câu trả lời:


31

Cá nhân, tôi đã thử tạo một lược đồ lớn cho tất cả các thực thể của mình trong một dự án khá phức tạp nhưng nhỏ (~ 300 bảng). Chúng tôi đã có một cơ sở dữ liệu cực kỳ chuẩn hóa (chuẩn hóa dạng thứ 5 (tôi nói là lỏng lẻo)) với nhiều mối quan hệ "nhiều đến nhiều" và thực thi toàn vẹn tham chiếu cực đoan.

Chúng tôi cũng đã sử dụng chiến lược "một trường hợp cho mỗi yêu cầu" mà tôi cũng không tin.

Khi thực hiện các danh sách "được xác định rõ ràng" đơn giản, bằng phẳng, việc tra cứu và lưu hiệu suất thường được chấp nhận. Nhưng khi chúng tôi bắt đầu đào sâu vào các mối quan hệ sâu sắc, màn trình diễn dường như mất đi sự quyết liệt. So với một Proc được lưu trữ trong trường hợp này, không có so sánh (tất nhiên). Tôi chắc chắn rằng chúng tôi đã điều chỉnh cơ sở mã ở đây và ở đó để cải thiện hiệu suất, tuy nhiên, trong trường hợp này, chúng tôi chỉ cần tăng hiệu suất mà không cần phân tích do hạn chế về thời gian và chúng tôi đã quay lại với Proc được lưu trữ (vẫn ánh xạ nó thông qua EF, vì EF cung cấp kết quả đánh máy mạnh mẽ), chúng tôi chỉ cần điều đó như là một sự trở lại trong một vài khu vực. Khi chúng tôi phải duyệt qua tất cả các cơ sở dữ liệu để tạo ra một bộ sưu tập (sử dụng .include () một cách không rõ ràng), hiệu suất đã giảm đáng kể, nhưng có lẽ chúng tôi đã yêu cầu quá nhiều ..

Vì vậy, dựa trên kinh nghiệm của tôi, tôi sẽ khuyên bạn nên tạo một .edmx riêng cho mỗi ý định. Chỉ tạo ra những gì bạn sẽ sử dụng dựa trên phạm vi của nhu cầu đó. Bạn có thể có một số tệp .edmx có phạm vi nhỏ hơn cho các tác vụ có mục đích và sau đó một số tệp lớn mà bạn cần duyệt qua các mối quan hệ phức tạp để xây dựng các đối tượng. Tôi không chắc vị trí kỳ diệu đó ở đâu, nhưng tôi chắc chắn có một ... lol ...

Thành thật mà nói, ngoài một vài cạm bẫy mà chúng ta thấy sắp tới (đi ngang phức tạp), .edmx khổng lồ đã hoạt động tốt từ góc độ "làm việc". Nhưng bạn sẽ phải coi chừng phép thuật "sửa lỗi" mà bối cảnh diễn ra sau bối cảnh nếu bạn không vô hiệu hóa nó một cách rõ ràng. Cũng như giữ cho .edmx đồng bộ hóa khi thay đổi cơ sở dữ liệu được thực hiện .. đôi khi dễ dàng hơn để xóa toàn bộ bề mặt và tạo lại các thực thể, mất khoảng 3 phút vì vậy nó không phải là vấn đề lớn.

Đây là tất cả với EntityFramework 4.1. Tôi thực sự muốn nghe về sự lựa chọn và kinh nghiệm cuối cùng của bạn.

Và liên quan đến câu hỏi của bạn trên nHibernate, theo ý kiến ​​của tôi, đó là một câu hỏi về giun, tôi sẽ bị sủa ở cả hai phía của hàng rào ... Tôi nghe thấy rất nhiều người đánh đập EF vì tội đánh đập mà không làm việc được thách thức và hiểu các sắc thái duy nhất cho chính EF .. và mặc dù tôi chưa bao giờ sử dụng nHibernate trong sản xuất, nói chung, nếu bạn phải tạo thủ công và rõ ràng những thứ như ánh xạ, tuy nhiên, bạn sẽ có quyền kiểm soát hữu hạn hơn, tuy nhiên, nếu bạn có thể kéo n 'drop, tạo và bắt đầu CRUD'ing và truy vấn bằng LINQ, tôi có thể đưa ra một tào lao về độ chi tiết.

Tôi hi vọng cái này giúp được.


1
FYI - Có một tiện ích lập bản đồ NHibernate giúp cho các ánh xạ này RẤT dễ dàng và tự động.
ganders

@ganders - Nó có UI và nó được tích hợp IDE như thế nào không? Tôi giả sử bạn trỏ nó vào một nguồn dữ liệu và nó tôn trọng tính toàn vẹn tham chiếu và truyền tải đối tượng và tạo các đối tượng ánh xạ?
hanzolo

1
Có nó (GUI). Tôi đã không có vấn đề với nó cho đến nay. Sử dụng nó trên 4 hoặc 5 dự án / trang web khác nhau. Lưu ý: Tôi sử dụng nó với Fluent NHibernate, ánh xạ trong mã c #, không phải trong tệp config / xml. Đây là một liên kết: nmg.codeplex.com
ganders

13

Hãy để tôi bắt đầu bằng cách làm rõ đơn giản: Tôi không có kinh nghiệm với cơ sở dữ liệu lớn như vậy nên phần còn lại của câu trả lời của tôi không dựa trên ví dụ trong thế giới thực.

Vì vậy, bạn có một cơ sở dữ liệu LỚN và bạn muốn sử dụng nó với ORM / EF. Tôi sẽ đi với sự lựa chọn thứ hai. Đây là lời giải thích đơn giản của tôi tại sao:

  • Ánh xạ thêm phức tạp. Không cần thêm độ phức tạp với các thực thể mà ứng dụng / dự án / mô-đun hiện tại của bạn không bao giờ cần nhưng đừng tạo mức độ chi tiết quá thấp. Có bộ ánh xạ riêng biệt trên mỗi màn hình cũng sẽ không giúp bạn.
  • Bạn muốn đạt được đơn vị công việc. Bạn sẽ có thể chỉ định mô-đun bảng nào cần trong hầu hết các trường hợp (không cần thiết trong mọi trường hợp). Nếu bạn đặt các bảng này vào bộ ánh xạ đơn, bạn sẽ có thể xử lý việc đọc và sửa đổi dữ liệu theo trường hợp ngữ cảnh đơn - đó là mục tiêu cuối cùng của bạn.
  • Tôi không chắc chính xác ý bạn là gì theo mô hình nhưng ngay cả với các bộ ánh xạ khác nhau, bạn có thể chia sẻ các lớp giữa các bộ ánh xạ bằng cách sử dụng cùng loại thực thể. Vì vậy, nếu bạn sử dụng bảng Người dùng trong hai mô-đun, bạn không cần hai lớp Người dùng để thể hiện giống nhau. Bạn vẫn có thể sử dụng bảng đơn và trong trường hợp ánh xạ mã (hay còn gọi là mã đầu tiên), bạn thậm chí có thể xác định ánh xạ một lần và tải nó vào nhiều bộ ánh xạ để nguyên tắc DRY không bị vi phạm nhưng cách tiếp cận mã đầu tiên có nhiều hạn chế hơn khi xuất hiện để xem và các thủ tục lưu trữ. EDMX làm cho điều này khó hơn. Bạn vẫn có thể sử dụng lại các lớp nhưng không thể sử dụng lại ánh xạ.
  • Điều gì về các truy vấn mô-đun chéo? Các truy vấn này có thể xảy ra nhưng thành thật mà nói, không phải mọi thứ đều phải được xử lý bởi EF. Bạn có thể tận dụng EF cho các trường hợp phổ biến để đơn giản hóa việc truy cập dữ liệu thông thường nhưng nếu bạn cần một truy vấn đặc biệt nào đó để tham gia các bảng thuộc 5 mô-đun khác nhau, bạn có thể thực hiện trực tiếp hoặc gói nó trong thủ tục được lưu trữ. 100% thay thế truy cập dữ liệu bản địa có thể khó khăn, phức tạp và chống sản xuất.
  • Điểm cuối cùng chỉ đơn giản là thực tế: Tôi không tin rằng công cụ VS đã sẵn sàng để làm việc với bộ đối tượng lớn như vậy - không phải trong nhà thiết kế, thậm chí không phải với công cụ nhập khẩu. Tôi đã từng làm việc trên cơ sở dữ liệu rất lớn với truy cập dữ liệu truyền thống và dự án Cơ sở dữ liệu SQL trong VS2008 - trải nghiệm người dùng với một dự án phức tạp là rất tệ. Bạn phải giữ số lượng bảng đã sử dụng ở mức thấp - giới hạn cho nhà thiết kế phải ở khoảng 100-200 nhưng thậm chí 100 bảng được xử lý bởi một ngữ cảnh (bộ ánh xạ) nghe có vẻ quá nhiều trách nhiệm đối với một lớp (giả sử rằng bạn sẽ có 100 thuộc tính được đặt tiếp xúc với bối cảnh - nó không giống như một thiết kế tốt).

4

Tôi muốn nói rằng bạn không thể quyết định loại câu hỏi này từ góc độ kỹ thuật. Tôi khuyên bạn nên xây dựng kiến ​​trúc của mình dựa trên các trường hợp sử dụng của bạn (câu chuyện của người dùng, v.v.). Đầu tiên tìm đối tượng kinh doanh của bạn. Một đối tượng thực thể không phải là một đối tượng kinh doanh mặc định. Điển hình bạn sẽ có một đối tượng kinh doanh trước các đối tượng thực thể. Sau đó, bạn có thể dần dần quyết định những gì bạn thực sự cần, dựa trên yêu cầu của người dùng.

"Một kiến ​​trúc sư giỏi tối đa hóa số lượng quyết định không được đưa ra." Robert C. Martin

http://cleancoder.posterous.com/arch architecture-deference


3

Tôi sử dụng phương pháp kết hợp - Công cụ OLTP được xử lý bởi EF trong khi các thao tác nặng như chèn hàng loạt, cập nhật hàng loạt, truy vấn báo cáo, v.v được xử lý bởi Procs Proored. Nó cũng làm cho đường dẫn di chuyển dễ dàng hơn nếu bạn không thực hiện viết lại toàn bộ lớp dữ liệu của mình cùng một lúc.


Đây có vẻ là một chiến lược tốt, nhưng thực sự không giải quyết được câu hỏi làm thế nào để phân chia các thực thể giữa các mô hình EF khác nhau. Bạn có tất cả các thực thể trong một mô hình hay bạn phân chia và chinh phục theo một cách nào đó?
RationalGeek

1
Nếu hiệu suất OLTP là đủ với cách tiếp cận mô hình đầy đủ, hãy đi với điều đó. Bạn luôn có thể phá vỡ nó sau nếu bạn phải, nhưng cách nhanh nhất và nhanh nhất là tải toàn bộ. Bạn có thể không bao giờ cần hiệu suất đạt được bằng cách phá vỡ nó, vì vậy bạn sẽ lãng phí thời gian và làm cho hệ thống của bạn trở nên phức tạp hơn mà không có lý do. Sau đó, có câu hỏi về mô hình nào bạn sẽ gắn một bảng / thực thể mới khi bạn quyết định mở rộng. Và điều gì xảy ra khi bạn cần chạy một bản cập nhật trên nhiều mô hình. Hãy tự cứu mình khỏi đau đầu trừ khi bạn thực sự không có cách nào khác.
Nik

Quên đề cập rằng bạn luôn có thể điều chỉnh hiệu suất của mình khi truy cập dữ liệu của mình. Nhìn vào các tùy chọn tải lười biếng / háo hức và các thực thể con bạn đang đưa vào. Tôi không hiểu lý do tại sao một mô hình đầy đủ sẽ hoạt động tồi tệ hơn một mô hình nhỏ hơn nếu bạn không tải các cây đối tượng lớn.
Nik

tôi muốn nói rằng các cây đối tượng khổng lồ và cấu trúc dữ liệu được chuẩn hóa sẽ song hành khi xử lý các lược đồ lớn
hanzolo

Bạn kiểm soát mức độ ít hoặc bao nhiêu bạn muốn bão hòa biểu đồ đối tượng.
Nik
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.