2012-04-19 31 views
9

Có thể thực hiện một nhóm theo đối tượng không?Nhóm khuôn khổ thực thểBằng một đối tượng hoặc loại phức tạp

from item in context.Items 
group item by item.MyObject 
select ... 

đâu Item.MyObject là một đối tượng đơn giản như:

public class MyObject { 
    public int SomeValue { get; set; } 
    public string SomeName { get; set; } 
    public string SomeOtherProperty { get; set; } 
} 

Rõ ràng tôi có thể làm như sau:

from item in context.Items 
group item by new { item.SomeValue, item.SomeName, item.SomeOtherProperty } 
select ... 

Tuy nhiên khi nhóm bởi các đối tượng với rất nhiều tài sản, cách tiếp cận này là tẻ nhạt và dễ bị lỗi.

Đoạn mã trên dẫn đến NotSupportedException với thông báo sau: "Loại bộ chọn khóa cho cuộc gọi đến phương pháp 'GroupBy' không thể so sánh được trong nhà cung cấp cửa hàng cơ bản". Overriding the Equals và GetHashcode không có hiệu lực. Tôi đoán vấn đề thực sự là khung thực thể không biết cách diễn đạt SQL ...?

+0

Phần 'MyObject' của mô hình EF? Tôi có thể làm điều tương tự với thuộc tính điều hướng trên 'MyObject' (trong đó MyObject: Item là n: 1). SQL được tạo ra là khủng khiếp, nhưng ít nhất nó hoạt động. –

+0

Nó thực sự là một loại phức tạp. Vì vậy, trong ngắn hạn có, EF là nhận thức của các loại đối tượng. Bởi vì tất cả các thuộc tính thực sự tồn tại trên cùng một bảng, tôi mong đợi kết quả SQL sẽ sạch hơn nhiều so với nếu nó đang sử dụng thuộc tính điều hướng (nếu tôi có thể làm cho nó hoạt động!) – mindlessgoods

Trả lời

7

Đáng tiếc, không, bạn không thể làm điều đó. ComplexType trông đầy hứa hẹn, và dường như là một "nhóm cột" đẹp đẽ - nhưng nhóm EF chỉ đơn giản là thiết kế nó để sử dụng hoàn toàn và tấn các tính năng liên quan đến việc sử dụng nó như là "nhóm cột" chỉ đơn giản là mất tích.

Theo như kiến ​​thức của tôi kéo dài, "Rõ ràng tôi có thể làm như sau:" là cách duy nhất có thể. Bạn chỉ cần xác định nhóm trên cơ sở từng cột phụ hoặc bằng phép chiếu đối với một số loại mà cơ sở dữ liệu sẽ biết cách so sánh.

Vấn đề cốt lõi là đội EF thấy complexType không phải là một nhóm các cột cho phép bạn dọn dẹp các đơn vị của bạn với nhiều lĩnh vực, nhưng, đối với họ, nó là một loại thực thể, loại một thoáng qua. Kiểu phức tạp có nghĩa là đại diện cho các đối tượng được trả về ví dụ từ một thủ tục được lưu trữ (hoặc các hàm trả về bảng) trả về một tập kết quả gồm 5 cột không thể ánh xạ tới bất kỳ bảng/lớp hiện có bình thường nào. Ví dụ, hãy tưởng tượng bạn có một bảng/lớp Khách hàng có chứa 50 cột/trường, hầu hết trong số chúng không phải là rỗng và đại diện cho một số dữ liệu nhạy cảm. Bạn tạo một thủ tục lưu sẵn lấy một ID của khách hàng và trả về {tên, địa chỉ, số điện thoại liên hệ, kích cỡ giày} của nó. Rõ ràng, có các kết quả được cắt tỉa được thiết lập, bạn không thể giải mã/ánh xạ nó vào lớp Khách hàng có hàng tấn các trường mà không thể là rỗng. Vậy làm thế nào để bạn đại diện cho tập kết quả thứ trong EF?

Tùy chọn đầu tiên, khá lame, chỉ đơn giản là bỏ qua EF và nói chuyện với cơ sở dữ liệu trực tiếp và đọc/dịch/giải nén các hàng/cột bằng tay. Vâng, chúng ta biết SqlClient, chúng ta có thể làm điều đó.

Tùy chọn thứ hai, xấu xí, là xác định trong EF bảng/chế độ xem, ví dụ CustomerView, chỉ chứa các cột {name, address, contact phone, shoe size} và ánh xạ bộ kết quả thủ tục đã lưu trữ cho nó. Nó sẽ hoạt động độc đáo, nhưng nếu bạn ngẫu nhiên 'tạo cơ sở dữ liệu' tạo thành mô hình EF, bạn sẽ nhận được thêm bảng chưa sử dụng đó.

Tùy chọn thứ ba để giải cứu là Loại phức tạp. Thay vì cố gắng tạo một bảng bóng hoặc khung nhìn, bạn chỉ cần nói với EF rằng "có một số kiểu dữ liệu bổ sung" mà sẽ không bao giờ được ánh xạ tới bảng riêng của nó và sẽ không bao giờ có một PrimaryKey được xác định và EF sẽ để thuận tiện, hãy ánh xạ nó tới một lớp như bất kỳ đối tượng dữ liệu nào khác. Bây giờ, có kiểu như vậy, bạn có thể trả lại nó từ các thủ tục và lấy nó như một đối tượng được nhập độc đáo, bạn có thể truyền nó như tham số của thủ tục, vv Nhưng: bạn không thể tự nó tồn tại. Nó không có ánh xạ bảng riêng và không có khóa chính riêng.Nó có không có nhận dạng.

Thật tuyệt vời, nhưng tốt, tại sao bạn muốn có kiểu dữ liệu như vậy được trả về từ quy trình? Có thể, quy trình được xử lý hoặc tạo một số dữ liệu và bạn muốn lưu trữ chúng trong một số bảng. Bạn đã không định nghĩa một thực thể bình thường, do đó, đó chỉ là một 'gói dữ liệu', vì vậy bạn có thể sẽ viết giá trị kết quả đó cho bảng đó cùng với các dữ liệu khác. Và đây là lý do tại sao EF cho phép bạn lập bản đồ cho một số cột của một bảng: nếu bạn nhận được đối tượng kết quả tạm thời đó từ một thủ tục và bây giờ bạn muốn viết nó ở đâu đó, bạn không phải thực hiện nó theo từng cột một cách thủ công , bạn chỉ cần ánh xạ nó vào cột "tên, địa chỉ, số điện thoại liên hệ, cỡ giày" của Khách hàng.

Điểm quan trọng nhất là, máy chủ cơ sở dữ liệu không bao giờ biết được loại phức tạp như vậy tồn tại. Như tôi đã nói, nó không có bản sắc. Khi bạn cố gắng làm một truy vấn LINQ như

aset.Where(item => item.complexProperty == complexValue) 

đó, complexValue là một đối tượng CLR có nghĩa là không ánh xạ tới bất kỳ bảng, có NO sắc, do đó NO PK, do đó EF có hoàn toàn NO IDEA làm thế nào để kiểm tra xem "đối tượng tay trái" giống như "đối tượng tay phải". Đã có các đối tượng xác định danh tính, nó có thể kiểm tra PK ở phía máy chủ, hoặc thực hiện so sánh đối tượng ở phía máy khách, nhưng ở đây - nó đơn giản là không thành công.

Tôi hoàn toàn đồng ý rằng đây là một tính năng hữu ích khác đáng tiếc trong EF bị thiếu. Tôi tin rằng nó sẽ là siêu dễ dàng cho đội EF để so sánh các ComplexTypes trên cơ sở từng cột, nhưng họ đã không. Họ chỉ đơn giản là không nghĩ rằng ComplexTypes có thể được sử dụng để dọn dẹp các bảng. Họ đã có nghĩa là nó là một gói dữ liệu thoáng qua để được chuyển đến và các thủ tục và các chức năng được lưu trữ từ .. Đáng tiếc.

+0

một lưu ý phụ: Tôi nói về so sánh , bởi vì tôi vừa mới tình cờ gặp phải điều đó khi tôi cố gắng lọc/nơi có một loại phức tạp. Nhóm là khác nhau tương tự, tất cả các boils xuống đến một 'không biết làm thế nào để so sánh' vấn đề. Nếu bất cứ ai biết cách giải quyết hoặc mở rộng EF - tôi cũng rất vui khi được biết về nó. Hiện tại, tôi chỉ tìm thấy các bài viết có nội dung 'xin lỗi, điều này chưa có sẵn, có lẽ trong EF5' – quetzalcoatl

+0

Cảm ơn câu trả lời chuyên sâu - đó là một tính năng tuyệt vời để xem trong các phiên bản sau. – mindlessgoods

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