2012-03-06 38 views
1

這可能是一個非常愚蠢而明顯的問題,但我對Linq很陌生。在我的數據訪問層類我有這樣的方法:linq語句返回什麼樣的對象?

static public ? GetAllUrls() 
     { 



      using (MonitoredUrlsEntities mu = new MonitoredUrlsEntities()) 
      { 


       var query = from urlTbl in mu.UrlLists 
          join histTbl in mu.Histories on 
          urlTbl.ID equals histTbl.UrlID 
          select new 
          { 
           urlTbl.Url, 
           urlTbl.UrlTitle, 
           urlTbl.UrlType, 
           urlTbl.Frequency, 
           urlTbl.Active, 
           urlTbl.LastChangeDate, 
           urlTbl.LastCheckDate, 
           histTbl.DateRun, 
           histTbl.HashValue 
          }; 

        return query.ToList(); 


      } 

問號是那裏,因爲我不知道什麼類型的對象的LINQ語句返回。我只是一個可以循環使用的列表。

+0

要看的語句,但通常IQueryable的。 – Jason 2012-03-06 16:22:54

回答

3

列表不能從方法返回匿名類型(如其他人所說的)。創建一個具體的類型和新的一個。你的返回類型爲IEnumerable<YourType>如下:

// NOTE: I do not know the actual types of these properties, YMMV 
public sealed class UrlHistoryList 
{ 
    public string Url { get; set; } 
    public string UrlTitle { get; set; } 
    public string UrlType { get; set; } 
    public int Frequency { get; set; } 
    public bool Active { get; set; } 
    public DateTime LastChangeDate { get; set; } 
    public DateTime LastCheckDate { get; set; } 
    public DateTime DateRun { get; set; } 
    public int HashValue { get; set; } 
} 

static public IEnumerable<UrlHistoryList> GetAllUrls() 
     { 



      using (MonitoredUrlsEntities mu = new MonitoredUrlsEntities()) 
      { 


       var query = from urlTbl in mu.UrlLists 
          join histTbl in mu.Histories on 
          urlTbl.ID equals histTbl.UrlID 
          select new UrlHistoryList 
          { 
           Url = urlTbl.Url, 
           UrlTitle = urlTbl.UrlTitle, 
           UrlType = urlTbl.UrlType, 
           Frequency = urlTbl.Frequency, 
           Active = urlTbl.Active, 
           LastChangeDate = urlTbl.LastChangeDate, 
           LastCheckDate = urlTbl.LastCheckDate, 
           DateRun = histTbl.DateRun, 
           HashValue = histTbl.HashValue 
          }; 

        return query.ToList(); 


      } 
+0

這是完美的!創建一個類並從方法中返回。 – Gandarez 2012-03-06 16:45:05

+0

我得到一個「無法初始化類型'ChangeDetection.UrlHistoryList'與集合初始值設定項,因爲它沒有實現'System.Collections.IEnumerable'。任何想法爲什麼會這麼說? – broke 2012-03-06 17:00:59

+3

@broke:因爲Jesse偶然給你的語法對於一個集合初始化器,而不是一個對象初始化器,應該是'... new UrlHistoryList {Url = urlTbl.Url,UrlTitle = urlTbl.UrlTitle ...' – 2012-03-06 17:08:49

1

嘗試IEnumerable

即使你刪除掉.ToList()這將是IQueryable

2

通常,LINQ語句返回一個IEnumerable/IQueryable的,因此你可以使用.ToList的原因()。在你的情況下,你正在返回一個列表,因爲.ToList(),但是。

如果去掉ToList(),我有你的回報爲IEnumerable如果你所希望做的是循環遍歷

6

您使用匿名類型的LINQ表達式的結果 - 而且,作爲文檔狀態:

您不能將方法的字段,屬性,事件或返回類型 聲明爲具有匿名類型。

http://msdn.microsoft.com/en-us/library/bb397696.aspx

+1

爲了解決這個問題,請創建一個類型,其中包含您選擇並返回的屬性/字段(列表)。 – 2012-03-06 16:25:09

3

嗯,這是一個List<T>,其中T一定的匿名類型,你不能在自己的代碼說(匿名類型給出了無法形容的名稱)。

故意這樣做;在本地使用之外傳播匿名類型通常是個錯誤。

您應該製作一個具體的類型,而不是使用匿名類型。稱它爲Foo。那麼你的返回類型將是List<Foo>

+1

*「匿名類型被賦予無法形容的名字」* - 比如「Voldemort」? – 2012-03-06 16:58:08

4

它返回匿名類型的列表,你不能從方法返回匿名類型(也許如果你使用動態,你可以但它是混亂的)。而不是使用匿名類型的創建與所有屬性的新類,並在投影填充:

var query = from urlTbl in mu.UrlLists 
      join histTbl in mu.Histories on 
       urlTbl.ID equals histTbl.UrlID 
      select new YourNewType 
      { 
       Url = urlTbl.Url, 
       UrlTitle = urlTbl.UrlTitle, 
       UrlType = urlTbl.UrlType, 
       Frequency = urlTbl.Frequency, 
       Active = urlTbl.Active, 
       LastChangeDate = urlTbl.LastChangeDate, 
       LastCheckDate = urlTbl.LastCheckDate, 
       DateRun = histTbl.DateRun, 
       HashValue = histTbl.HashValue 
      }; 

現在,你的方法可以返回IEnumerable<YourNewType>

+1

或者它可能是'object'。 – jason 2012-03-06 16:24:13

+1

@Jason:但在這種情況下,您將完全失去對內部數據的訪問權限。 – 2012-03-06 16:27:58

+0

咦?不可以。您可以投射或使用反射。 – jason 2012-03-06 16:53:50

2

它返回IQueryable<T>其中T是在select new部分定義的匿名對象的查詢。

最後,它返回一個List<T>

方法簽名也許應該是:public static List<dynamic> GetAllUrls() 因爲static public ? GetAllUrls()似乎無效。

1

在這個例子中,你正在返回上IQueryable<T>類型的匿名對象基礎,以便能夠重複這樣的

foreach (var item in query) 
{ 
    //you could access to each attribute of the object like this 

    string url = item.Url 
    string urlTittle = item.UrlTittle 
} 
1

由於一些答案已經注意到,您在使用方法的返回類型麻煩,因爲它是一個匿名類型。有幾個技巧可以用來解決這個問題;他們主要涉及在呼叫站點GetAllUrls處定義匿名類型,將GetAllUrls定義爲通用方法,並允許編譯器的類型推斷完成其餘部分。

但是,在這種情況下,最好確保EF和數據庫在URL和歷史記錄之間定義關係,並使用EF從每個URL獲取歷史記錄(反之亦然)。例如:

foreach (var url in mu.UrlLists) 
    foreach (var history in url.Histories) 
    { 
     var obj = new {  
          url.Url,  
          url.UrlTitle,  
          url.UrlType,  
          url.Frequency,  
          url.Active,  
          url.LastChangeDate,  
          url.LastCheckDate,  
          history.DateRun,  
          history.HashValue  
         }; 
     // do something with obj 
    } 

或只是

foreach (var url in mu.UrlLists) 
    foreach (var history in url.Histories) 
     //do something with url and history 
11

正如其他人指出,這種特定查詢的結果涉及的匿名類型。因此,您不能註釋該方法爲返回本地變量的確切類型,因爲無法鍵入該類型的名稱,因爲它沒有名稱;這就是「匿名」的意思。

可以說,該方法返回IEnumerable<object>IEnumerableobject甚至dynamic,但可能是更好的事情做的是使查詢首先返回名義類型的序列。

更普遍的:正如其他人指出,查詢通常在實踐某種IEnumerableIQueryable類型。然而,認識到LINQ表達式不一定具有任何特定類型是很重要的。 LINQ實現爲句法轉換,而不是語義轉換。當你說:

var query = from c in customers select c.Name; 

編譯器將是盲目進入:

var query = customers.Select(c=>c.Name); 

類型的query是什麼方法Select恰好返回。它可能是int!它幾乎肯定不是,因爲那將是,但是如果某個不正當的人決定製作一個名爲Select的方法返回int,那麼查詢將是int類型。

事實證明,我只是這樣一個乖張的人;我給使用LINQ到這裏操縱整數的例子:

http://blogs.msdn.com/b/ericlippert/archive/2009/12/07/query-transformations-are-syntactic.aspx

+1

謝謝信息!您的博客岩石順便說一句。 – broke 2012-03-06 17:24:48