2010-01-28 75 views
5

我正在使用LINQ to Entities。爲什麼這個linq表達式不起作用?

我有一張名爲Student的表;它具有ID和名稱,因爲它是列。 ID是主鍵。

我希望能夠選擇學生的姓名並獲得具有相同姓名的學生人數。

因此,例如,我會把這個作爲我的表格數據。

ID Name 
1 Bob 
2 Will 
3 Bob 

執行查詢後,我會返回一個Student對象列表,看起來像這樣。

Name Quantity 
Bob  2 
Will 1 

我想這有點類似於stackoverflow標籤頁的工作原理;它有名字和數量。

無論如何,我創建了一個名爲Student.cs的部分類,其中我添加了一個像這樣的數量屬性。

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; } 
     } 
    } 
} 

我想出了這一點,但我得到一個錯誤..

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; 
    } 

,我發現了錯誤說像無法從類型轉換匿名向學生名單。它與它沒有關係,不能識別我在分部類中添加的數量字段?

謝謝!

+0

一些一般性的建議是:直到你獲得更多的經驗停止使用VAR 。如果你曾嘗試使用'IQueryable =(來自...',那麼你就會在問題上得到更快的處理速度。 – 2010-01-28 20:56:49

回答

4

更改Student類型,看起來像這樣:

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

和您的查詢,看起來像這樣:

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

您的方法將返回IQueryable<Student>,但您當前正在返回預計匿名類型的IQueryable<T>

您需要重構自己Student類型有String類型的Name屬性,然後投影手機從表達Student類型的新實例,使您的表達式的返回類型將匹配你的方法的返回類型。

+0

修復bug不是「重構」。而且上面定義的Student具有一個Name,因爲它是一個從具有Name和ID的Linq對象擴展而來的部分類。 現在擴展學生添加數量肯定是有問題的,但是...... – 2010-01-28 20:03:02

+0

擴展Student類以添加數量屬性是一個壞主意嗎?我沒有數據庫中的學生數量列。我想返回一個Student對象列表,所以在我的View中(繼承Student對象),我可以很容易地顯示數量。有沒有不同的/更好的方法呢? – hanesjw 2010-01-28 20:11:44

+0

是的,這是一個壞主意 - 我在查看代碼而不是整個圖片。 – 2010-01-28 20:21:12

2

問題是你沒有返回學生 - 你試圖從你的函數返回一個匿名類型。這是不允許的。

創建一個類來表示您的結果,並在您的查詢中使用new MyClass { ... }而不是new { ... },並將方法更改爲返回IQueryable<MyClass>而不是IQueryable<Student>

例如,您可以創建一個名爲StudentNameAndResults的類。

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

或者,您可以將結果作爲字典或IGrouping的IEnumarable返回。例如:

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); 
} 

另外,您創建的屬性使用的是C#3.0以前的詳細語法。現在你可以使用auto-implemented properties如果你不需要任何特殊的邏輯:

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()}); 

這是一個匿名類型,而不是IQueryable<Student>。無論你需要返回System.Object,或者你需要返回IQueryable<Student>如下...

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

凡學生定義了initializtion使用的屬性。

+0

儘管您可以將匿名類型返回爲System.Object,但它並沒有什麼幫助,因爲除非將其轉換爲正確的子類型,否則不能使用這些字段,並且您不知道該類型是什麼類型。我不會推薦這樣做。 – 2010-01-28 20:31:16

2

select new關鍵字導致數據的形式發生變化,這意味着LINQ查詢不會返回IQueryable <學生>,而是包含「名稱」和「數量」屬性的匿名類型。如果您將其更改爲返回具體類型而不是匿名類型,您將能夠以所需的形式檢索數據。

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

不知道最後的那個AsQueryable()會起作用嗎? – 2010-01-29 00:41:51

2

你的函數返回學生

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

但是你的Linq查詢返回一個新的類型,包含一個名稱和一個int(計數)

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

的y嘗試選擇新的學生{ Name = g.Key,Quantity = g.Count()}

1

您正在linq查詢中進行投影。如果你將光標懸停在var students裏面,你會看到它的一個匿名類型的集合。

如果你想回到你需要做一個IQueryabley<Student>

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

沒有辦法以外的方法可以知道你已經在你前面的例子中創建的匿名類型,所以你將不能夠返回一個類型化的集合。

隨着我建議你還是可以做一個投影在你的方法的返回值以後,由於IQueryable的是組合的,直到第一個枚舉的方法:

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

我認爲問題在於'Student'在數據庫中沒有'Quantity',他試圖將它添加到類中並將其設置在此查詢中。所以,如果你使用了你的建議,我會猜測'數量'將始終設置爲0。 – 2010-01-28 20:28:01

2

方法的返回值的關係的「students」集合到IQueryable<Student>但是... Linq表達式創建了一個IQueryable<some anonymous type>,並且兩者之間沒有轉換。

你可能會得到一個嬰兒通過修改選擇部分有待進一步步驟:

select new Student() {....} 

希望這有助於,

泰勒

相關問題