2010-04-17 30 views

Trả lời

18

Ví dụ hoàn hảo là địa chỉ. Sử dụng một loại phức tạp cho một địa chỉ dễ dàng hơn nhiều để đối phó với một thực thể mới. Với các loại phức tạp, bạn không phải đối phó với khóa chính. Hãy suy nghĩ về việc truy cập vào một địa chỉ có bao nhiêu loại thực thể phổ biến sẽ có một địa chỉ (Business Units, People, Places). Hãy tưởng tượng nhập địa chỉ của nhiều người và cần đặt khóa cho từng địa chỉ. Với các kiểu phức tạp, bạn chỉ cần truy cập các thuộc tính nội bộ của chúng và bạn đã hoàn thành. Đây là một liên kết MSDN của một ví dụ. http://msdn.microsoft.com/en-us/library/bb738613.aspx

+2

Điều gì sẽ là lợi thế của việc có loại phức tạp thay vì các thuộc tính vô hướng đồng bằng? – emzero

+0

@emzero Tôi đoán chúng rất nhiều, về cơ bản đây là một OOD. Bạn có thể không định nghĩa phương thức get trên Address hoặc truyền một đối tượng địa chỉ cho một số phương thức khác khi gửi một lô hàng. Nó cũng tuân theo phương pháp DRY. Giả sử bạn làm một ToString() override, bạn chỉ phải làm điều đó một lần cho tất cả các lớp có Address. –

+0

Điều này có gây khó khăn khi thực hiện thao tác trên tất cả các địa chỉ của tất cả các bảng khác nhau không? Điều gì sẽ xảy ra nếu tôi muốn thêm dữ liệu vị trí địa lý hoặc xóa tất cả định dạng địa chỉ, v.v ...? Sẽ không phải tất cả điều này dễ dàng hơn nhiều với bảng riêng biệt? Hoặc bạn có thể làm điều gì đó như repo.ComplexTypes.ToList() –

0

Dựa trên khái niệm thiết kế Driven miền, tổng hợp gốc có thể có một hoặc nhiều đối tượng bên trong làm bộ phận của nó. Trong trường hợp này, các đối tượng bên trong - bên trong ranh giới của Tổng hợp gốc - không có bất kỳ KEY nào. Khóa cha sẽ được áp dụng cho chúng hoặc bằng cách nào đó như thế này. Câu trả lời của bạn trả về lợi ích của việc giữ tất cả các phần bên trong gốc tổng hợp làm cho mô hình của bạn mạnh mẽ hơn và đơn giản hơn nhiều.

+0

Gốc tổng hợp có thể chứa các thực thể, có các khóa. Chúng chỉ thuộc về một gốc tổng hợp. –

10

Câu hỏi này đã ở đây một thời gian rồi, nhưng tôi sẽ thêm một câu trả lời dù sao với hy vọng rằng tiếng nức nở nghèo tiếp theo đến cùng biết những gì anh ta đang làm.

Các loại phức tạp không hỗ trợ tải chậm, ít nhất không phải trong EF 4.3. Hãy lấy tình huống địa chỉ làm ví dụ. Bạn có bảng Person với 15 cột, 5 cột chứa thông tin địa chỉ cho một số cá nhân. Nó có 50k hồ sơ. Bạn tạo thực thể Person cho bảng với một loại địa chỉ phức tạp.

Nếu bạn cần một danh sách tên của tất cả các cá nhân trong cơ sở dữ liệu của bạn, bạn sẽ làm gì

var records = context.Persons; 

mà còn bao gồm địa chỉ, bơm 5 * 50k giá trị vào danh sách của bạn không có lý do và có sự gián đoạn đáng chú ý. Bạn có thể chọn chỉ tải các giá trị bạn cần trong một loại ẩn danh với

var records = from p in context.Persons 
       select new { 
       LastName = p.LastName, 
       FirstName = p.FirstName, 
       } 

hoạt động tốt cho trường hợp này, nhưng nếu bạn cần danh sách toàn diện hơn với 8 cột không phải địa chỉ bạn cần để thêm từng loại trong loại ẩn danh hoặc chỉ cần đi với trường hợp đầu tiên và quay trở lại để tải dữ liệu địa chỉ vô ích. Đây là những điều về các loại vô danh: Trong khi chúng rất hữu ích trong một phương pháp duy nhất, chúng buộc bạn sử dụng các biến động ở nơi khác trong lớp hoặc lớp con của bạn, loại bỏ một số cơ sở tái cấu trúc của Visual Studio và để bạn mở để chạy lỗi thời gian. Lý tưởng nhất là bạn muốn lưu hành các thực thể giữa các phương pháp của mình, vì vậy những thực thể đó phải mang theo ít hành lý nhất có thể. Đây là lý do tại sao lười biếng tải là rất quan trọng.

Khi nói đến ví dụ trên, thông tin địa chỉ thực sự phải nằm trong một bảng riêng của nó với một thực thể thổi toàn bộ bao gồm nó. Là một lợi ích phụ, nếu khách hàng của bạn yêu cầu một địa chỉ thứ hai cho một người, bạn có thể thêm nó vào mô hình của bạn bằng cách thêm một tham chiếu Địa chỉ bổ sung trong Person.

Nếu không giống như ví dụ trên, bạn thực sự cần dữ liệu địa chỉ trong hầu hết mọi truy vấn bạn thực hiện và thực sự muốn có các trường đó trong bảng Person, sau đó chỉ cần thêm chúng vào thực thể Person. Bạn sẽ không có tiền tố Địa chỉ gọn gàng nữa, nhưng nó không chính xác là cái gì đó để mất ngủ.

Nhưng hãy đợi, còn nhiều hơn nữa!

Loại phức tạp là một trường hợp đặc biệt, một vết sưng trên cảnh quan trơn tru của các thực thể EF thuần túy.Những cái trong dự án của bạn có thể không đủ điều kiện để kế thừa từ lớp cơ sở thực thể của bạn, làm cho nó không thể đặt chúng thông qua các phương thức xử lý các thực thể của bạn nói chung.

Giả sử rằng bạn có một lớp cơ sở thực thể có tên EntityModel xác định ID thuộc tính. Đây là chìa khóa cho tất cả các đối tượng thực thể của bạn, vì vậy bây giờ bạn có thể tạo

class EntityModelComparer<T> : IEqualityComparer<T> where T : EntityModel 

mà sau đó bạn có thể sử dụng với biệt() để lọc các bản sao từ bất kỳ IQueryable của loại T trong đó T là một lớp thực thể. Một loại phức tạp không thể kế thừa từ EntityModel vì nó không có thuộc tính ID, nhưng điều đó là tốt bởi vì bạn sẽ không sử dụng riêng biệt trên nó.

Tiếp tục xuống dòng bạn gặp phải tình huống mà bạn cần một số cách để thực hiện bất kỳ thực thể nào và thực hiện thao tác. Có thể bạn muốn tự động liệt kê các thuộc tính của một thực thể trên giao diện người dùng và cho phép người dùng thực hiện các truy vấn trên chúng. Vì vậy, bạn xây dựng một lớp mà bạn có thể khởi tạo cho một loại cụ thể và có thể chăm sóc toàn bộ điều đó:

public class GenericModelFilter<T> : where T : EntityModel 

Xin chờ, loại phức tạp của bạn không thuộc loại EntityModel. Bây giờ bạn phải làm phức tạp cây thừa kế thực thể của bạn để chứa các kiểu phức tạp hoặc loại bỏ hợp đồng EntityModel và giảm khả năng hiển thị.

Moving cùng, bạn thêm một phương pháp để lớp học của bạn mà dựa trên sự lựa chọn sử dụng có thể tạo ra một biểu thức mà bạn có thể sử dụng với LINQ để lọc bất kỳ lớp thực thể

Expression<Func<T, bool>> GetPredicate() { ... } 

vì vậy bây giờ bạn có thể làm một cái gì đó như thế này:

personFilter = new GenericModelFilter<Person>(); 
companyFilter = new GenericModelFilter<Company>(); 
addressFilter = new GenericModelFilter<Address>(); //Complex type for Person 

... 

var query = from p in context.Persons.Where(personFilter.GetPredicate()) 
      join c in context.Companies.Where(companyFilter.GetPredicate()) on p.CompanyID = c.ID 
      select p; 

Điều này cũng tương tự cho tất cả các đối tượng thực thể ... ngoại trừ Địa chỉ với các nhu cầu đặc biệt của nó. Bạn không thể tham gia vì nó giống như bạn đã làm với Công ty. Bạn có thể điều hướng đến nó từ Person, nhưng làm thế nào để bạn áp dụng Expression trên nó và vẫn kết thúc với Person ở cuối? Bây giờ bạn phải mất thời gian và tìm ra trường hợp đặc biệt này cho một hệ thống đơn giản hoạt động dễ dàng ở mọi nơi khác.

Mẫu này lặp lại trong suốt thời gian tồn tại của dự án. Tôi có nói từ kinh nghiệm không? Tôi ước gì không. Các loại hình phức tạp tiếp tục ngăn chặn sự tiến bộ của bạn, giống như một học sinh bị khiếm khuyết ở mặt sau của lớp học, mà không cần thêm bất cứ điều gì về bản chất. Làm cho bạn một ưu tiên và lựa chọn cho các đối tượng thực thể thực tế để thay thế.

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