2008-12-21 20 views
5

Tôi đang sử dụng LINQ to EF và có các truy vấn LINQ sau:Sử dụng LINQ làm thế nào để tôi có một nhóm bởi một "lĩnh vực tính toán"

var results = (from x in ctx.Items 
       group x by x.Year into decades 
       orderby decades.Count() descending 
       select new { Decade = decades.Key, DecadeCount = decades.Count() }); 

Vì vậy, hình thức này được tôi đến nơi tôi muốn trở thành, trong đó tôi nhận được các mặt hàng được chia nhỏ theo năm và số lượng mặt hàng trong năm đó. (tức là 2001 - 10, 1975 - 15, 2005 - 5, 1976 - 1) Điều tôi thực sự muốn làm là phá vỡ chúng theo thập kỷ (tức là năm 2000 - 15, 1970 - 16).

Làm cách nào có một "trường được tính toán" trong phần "bởi" của mệnh đề nhóm cho câu lệnh Linq. Tôi nghĩ rằng những gì tôi muốn về cơ bản giống như:

var results = (from x in ctx.Items 
       group x by (x => x.Year.Value.ToString().Substring(0, 3) + "0s") into decades 
       orderby decades.Count() descending 
       select new { Decade = decades.Key, DecadeCount = decades.Count() }); 

Hoặc thường là cú pháp để tôi có thể thực hiện một số đánh giá/tính toán phức tạp hơn để thực hiện từng nhóm. Bất kỳ ý tưởng?

EDIT (cập nhật):

(. X => x.Year.Value.ToString() substring (0, 3) + "0s") - không hoạt động - "LINQ to Entities không nhận ra phương thức 'System.String ToString()' và phương thức này không thể được dịch sang biểu thức cửa hàng. "

(x.Year/10 * 10) - Về mặt chức năng công trình (cảm ơn bạn) - các "vấn đề" duy nhất là 's' không phải là ở cuối dòng (tức là năm 1970 so với năm 1970)

Có anyway để đặt một hàm trong mệnh đề by? tức là nhóm x bởi this.ManipulateYear (x.Year) thành nhiều thập kỷ ... hoặc ... x => x.Year.Value.ToString(). Chuỗi con (0,3) + "0s" ?? Sẽ tốt hơn nếu có một số kỹ thuật (chẳng hạn như gọi một hàm hoặc sử dụng một biểu thức lambda) để tôi có thể bao gồm bất kỳ trường hợp nào mà tôi có thể nghĩ đến.

Cảm ơn một lần nữa vì sự giúp đỡ của mọi người về vấn đề này.

Trả lời

2

Dường như chúng ta không thể làm một nhóm hoặc chọn hoặc tương tự trên lĩnh vực tính toán được definied trong các lớp học phần trên thực thể khuôn khổ.

Các lĩnh vực tính toán có thể được sử dụng trên LINQ to đối tượng (do đó bạn có thể trả lại tất cả các dữ liệu như các đối tượng và sau đó làm một nhóm)

0

Tôi tin rằng bạn sẽ chuỗi phương pháp SelectMany vào cuối kết quả của bạn. Điều này trả về một IEnumerable của IEnumerables.

+1

Không, một nhóm đã là một IEnumerable của IEnumerables (như IGrouping kéo dài IEnumberable). Không cần SelectMany ở đây. –

6

Cách phân nhóm theo x.Year/10? (Chưa được thử nghiệm này!)

var results = (from x in ctx.Items 
       group x by (x.Year/10 * 10) into decades 
       orderby decades.Count() descending 
       select new { Decade = decades.Key, DecadeCount = decades.Count() }); 

EDIT1: Thay đổi (x.Year/10) đến (x.Year/10 * 10) để có được, ví dụ, 1980 thay vì 198.

EDIT2: Trong ví dụ của bạn, "nhóm x bởi x.Year.Value.ToString(). Chuỗi con (0, 3) +" 0s ") vào nhiều thập kỷ" cũng nên hoạt động. Không cần cú pháp lamba.

EDIT3: Đã xóa thêm * 10. Cảm ơn Marc!

+0

Trong LINQ to-đối tượng nên được tốt. Với EF, bạn cần phải kiểm tra lại cách tính số học (int/float/etc). Bạn có thể muốn 'Toán học.Ví dụ: Floor (x.Year/10) * 10' - giả định rằng EF có thể ánh xạ 'Math.Floor' thành' FLOOR' của TSQL. –

+0

Ồ, bạn có thể có * 10 hai lần (một lần trong 'nhóm', một lần trong' chọn mới') –

+0

.ToString() không hoạt động (không thể ánh xạ tới lỗi kiểu SQL) - tôi đã không thử nghiệm giải pháp "toán học" nhưng có vẻ như nó có thể giải quyết trường hợp này. tôi muốn konw làm thế nào để làm điều đó cho tất cả các trường hợp (tức là những người không có một giải pháp loại toán học hoặc những người cần một loạt các báo cáo nếu hoặc tương tự). – ChrisHDog

7

Bạn có thể sử dụng mệnh đề let để tránh đếm thập kỷ nhiều lần:

from x in ctx.Items 
group x by (x.Year/10 * 10) into decades 
let decadeCount = decades.Count() 
orderby decadeCount descending 
select new { Decade = decades.Key, DecadeCount = decadeCount } 
+0

Điểm tốt. Nó có thể sẽ không tạo ra sự khác biệt trong LINQ to SQL, nhưng chắc chắn sẽ giúp bạn tiết kiệm thêm một Count() trong LINQ to Objects. – Lucas

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