2010-01-28 43 views
5

Tôi đang sử dụng LINQ to Entities.Tại sao biểu thức LINQ này không hoạt động?

Tôi có một bảng có tên Sinh viên; nó có ID và Tên là các cột của nó. ID là khóa chính.

Tôi muốn có thể chọn tên của Sinh viên và nhận số tiền Học sinh có cùng tên.

Vì vậy, ví dụ: tôi có dữ liệu bảng này.

ID Name 
1 Bob 
2 Will 
3 Bob 

Sau khi thực hiện truy vấn, tôi sẽ trả về Danh sách đối tượng sinh viên như thế này.

Name Quantity 
Bob  2 
Will 1 

Tôi đoán nó tương tự như cách trang Thẻ ngăn xếp hoạt động; Nó có tên và số lượng.

Dù sao, tôi đã tạo một lớp học có tên là Student.cs, trong đó tôi đã thêm thuộc tính Số lượng như thế này.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

namespace MySite.Models 
{ 
    public partial class Student 
    { 
     private int _quantity; 

     public int Quantity 
     { 
      get { return _quantity; } 
      set { _quantity = value; } 
     } 
    } 
} 

tôi đến với điều này nhưng tôi nhận được một lỗi ..

public IQueryable<Student> FindStudentsDistinctWithQuantity() 
    { 
     /*SELECT Name, COUNT(Name) AS Quantity 
     FROM Student 
     GROUP BY Name*/ 

     var students= (from s in db.Students 
        group s by s.Name into g 
        select new {Name = g.Key, Quantity = g.Count()});    

     return students; 
    } 

Các lỗi tôi nhận được nói cái gì đó như không thể chuyển đổi từ loại Chưa xác định vào danh sách sinh viên. Liệu nó có liên quan gì đến việc nó không nhận ra trường số lượng mà tôi đã thêm vào trong một phần không?

Cảm ơn!

+0

Một số lời khuyên chung: ngừng sử dụng var cho đến khi bạn có được nhiều kinh nghiệm . Nếu bạn đã cố gắng sử dụng 'IQueryable = (từ ...' bạn sẽ có số không nhanh hơn nhiều trong vấn đề. –

Trả lời

4

Thay đổi loại Student của bạn trông như thế này:

public partial class Student 
{ 
    public Int32 Quantity { get; set; } 
    public String Name { get; set; } 
} 

Và truy vấn của bạn trông như thế này:

var students = from s in db.Students 
       group s by s.Name into g 
       select new Student { 
        Name = g.Key, 
        Quantity = g.Count() }; 

Phương thức của bạn trả về số IQueryable<Student> nhưng hiện tại bạn đang trả về IQueryable<T> của loại ẩn danh dự kiến.

Bạn cần phải cấu trúc lại loại Student của bạn để có một loại tài sản của StringName và sau đó dự án trường hợp mới của Student loại hình từ biểu thức để các kiểu trả về của biểu hiện của bạn sẽ phù hợp với kiểu trả về của phương pháp của bạn.

+0

Nó không phải là "tái cấu trúc" để sửa lỗi.Và sinh viên như ông đã có nó được định nghĩa ở trên có một tên, bởi vì nó là một phần lớp mở rộng từ đối tượng Linq của mình có tên và ID. Bây giờ việc mở rộng Học sinh để thêm số lượng chắc chắn là vấn đề nhưng .... –

+0

Bạn có nên mở rộng lớp Học sinh để thêm thuộc tính số lượng không? Tôi không có một cột số lượng trong cơ sở dữ liệu cho sinh viên. Tôi muốn trả về một danh sách các đối tượng của Học sinh trong Chế độ xem của tôi (mà kế thừa đối tượng Sinh viên), tôi có thể dễ dàng hiển thị Số lượng. Có cách nào khác tốt hơn để làm điều đó không? – hanesjw

+0

Vâng, đó là một ý tưởng tồi - Tôi đã xem mã và không phải toàn bộ hình ảnh. –

2

Sự cố là bạn không trả lại sinh viên - bạn đang cố gắng trả về loại ẩn danh từ chức năng của mình. Điều này không được phép.

Tạo lớp để trình bày kết quả của bạn và sử dụng new MyClass { ... } thay vì new { ... } trong truy vấn của bạn và thay đổi phương thức trả lại IQueryable<MyClass> thay vì IQueryable<Student>.

Ví dụ: bạn có thể tạo một lớp có tên là StudentNameAndResults.

class StudentNameAndResults 
{ 
    public string Name { get; set; } 
    public int Quantity { get; set; } 
} 

Ngoài ra, bạn có thể trả lại kết quả dưới dạng Từ điển hoặc In thể duyệt IGroup. Ví dụ:

public IDictionary<string, int> FindStudentsDistinctWithQuantity() 
{ 
    Database db = new Database(); 
    var students= (from s in db.Students 
       group s by s.Name into g 
       select new {Name = g.Key, Quantity = g.Count()}); 

    return students.ToDictionary(s => s.Name, s => s.Quantity); 
} 

Ngoài ra, thuộc tính bạn đã tạo đang sử dụng cú pháp chi tiết từ trước C# 3.0 ngày. Bây giờ bạn có thể sử dụng auto-implemented properties nếu bạn không cần bất kỳ logic đặc biệt:

public int Quantity { get; set; } 
1
var students= (from s in db.Students 
        group s by s.Name into g 
        select new {Name = g.Key, Quantity = g.Count()}); 

Đây là loại ẩn danh, không phải IQueryable<Student>. Hoặc là bạn cần phải trả lại System.Object, hoặc bạn cần phải trả lại IQueryable<Student> như sau ...

return from s in db.Students 
     group s by s.Name into g 
     select new Student{Name = g.Key, Quantity = g.Count()}; 

đâu Sinh viên định nghĩa các thuộc tính được sử dụng trong initializtion.

+0

Trong khi bạn có thể trả về một kiểu ẩn danh là System.Object, nó không giúp ích nhiều bởi vì bạn không thể sử dụng các trường trừ khi bạn đưa nó vào đúng kiểu con, và bạn không biết loại đó là gì. Tôi sẽ không khuyên bạn nên làm điều này. –

2

Các select new từ khóa đang gây ra dưới dạng dữ liệu thay đổi, có nghĩa là truy vấn LINQ sẽ không trở lại một IQueryable <Student>, mà đúng hơn là một loại vô danh chứa "Tên" và "Số lượng" tài sản. Nếu bạn thay đổi nó để trả về một loại cụ thể thay vì một kiểu ẩn danh, bạn sẽ có thể lấy dữ liệu dưới dạng bạn muốn.

public class StudentGrouping { 
    public string Name { get; set; } 
    public int Quantity { get; set; } 
} 

public IQueryable<StudentGrouping> FindStudentsDistinctWithQuantity() 
{ 
    /*SELECT Name, COUNT(Name) AS Quantity 
    FROM Student 
    GROUP BY Name*/ 

    var students= (from s in db.Students 
       group s by s.Name into g 
       select new StudentGrouping { 
        Name = g.Key, 
        Quantity = g.Count() 
       }).AsQueryable();    

    return students; 
} 
+0

Bạn không chắc chắn về điều đó AsQueryable() vào cuối sẽ hoạt động? –

2

Chức năng của bạn trả về Student

public IQueryable<Student> FindStudentsDistinctWithQuantity(){ ... } 

Nhưng truy vấn LINQ của bạn trả về một loại mới có chứa một tên và một Int (count)

   >>> select new {Name = g.Key, Quantity = g.Count()});    

y cố gắng chọn Sinh viên mới { Tên = g.Key, Quantity = g.Count()}

1

Bạn đang thực hiện phép chiếu trong truy vấn LINQ của mình. Nếu bạn di chuột qua var students bên trong và bạn sẽ thấy bộ sưu tập của một loại ẩn danh.

Nếu bạn muốn quay trở lại một IQueryabley<Student> bạn cần làm:

var students= from s in db.Students 
        group s by s.Name into g 
        select s.Key; 

Không có cách nào phương pháp bên ngoài có thể biết về các loại vô danh bạn đã tạo ra trong ví dụ trước đây của bạn, vì vậy bạn sẽ không thể để trả lại bộ sưu tập đã nhập.

Với phương pháp tôi đề nghị bạn vẫn sẽ có thể làm một dự báo về giá trị trả về của phương pháp của bạn sau này, kể từ IQueryable là composable cho đến khi liệt kê đầu tiên:

var students = FindStudentsDistinctWithQuantity(); 
var namesAndQunatity = from s in students select new {s.Name, s.Quantity}; 
+0

Tôi nghĩ rằng vấn đề là 'Sinh viên' không có 'Số lượng' trong cơ sở dữ liệu và anh ấy đang cố gắng thêm nó vào lớp và đặt nó bên trong truy vấn này. Vì vậy, nếu bạn đã sử dụng đề xuất của mình, tôi sẽ đoán rằng 'Số lượng' sẽ luôn được đặt thành 0. –

2

quan hệ giá trị trả về Phương pháp của các Bộ sưu tập "students" tới IQueryable<Student> nhưng ... biểu thức LINQ đang tạo một IQueryable<some anonymous type> và không có chuyển đổi nào giữa hai loại.

Bạn có thể nhận một đứa bé bước xa hơn bằng cách thay đổi lựa chọn một phần của bạn là:

select new Student() {....} 

Hy vọng điều này giúp,

Tyler

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