2010-08-13 58 views
1

我很新仍然在C#所以我可能會做一些愚蠢的事情,但我已經花了一些時間看這個,仍然無法看到問題是什麼。最後一個()方法不工作在IQueryable對象

下面是一些代碼片段:

 double work = 0; 
     ProjectRepository pr = new ProjectRepository(); 
     IQueryable<CalendarDetail> cds; 

     // Find matching day of week 
     // Then for that day, cycle through all working times 

     // Return list of working times in day 
     cds = pr.GetCalDetails(calendarID, startTime.DayOfWeek.GetHashCode()); 

     foreach (CalendarDetail cd in cds) 
     { 
      DateTime wts = startTime.Date + cd.WorkingTimeStart.Value.TimeOfDay; 
      DateTime wtf = startTime.Date + cd.WorkingTimeFinish.Value.TimeOfDay; 

      //more code here.... 

      if ((cds.Last().CalendarDetailID == cd.CalendarDetailID) && (finishTime > wtf)) 
       work += Work(startTime.Date.AddDays(1), finishTime, calendarID); 
     } 

錯誤被拋出運行時,由於我使用cds.Last()方法調用的。但是,已經聲明瞭cds並將其用作IQueryable對象,那麼問題是什麼?

錯誤文本: 查詢運算符'Last'不受支持。

未能解決方案我相信我可以用邏輯解決問題,但這看起來很優雅。

感謝,

喬納森

+0

你可以發佈你的異常? – 2010-08-13 11:24:40

+0

拋出什麼錯誤? – 2010-08-13 11:25:20

+2

嘿,我剛剛意識到你使用了[wtf](http:// thedailywtf。com /)作爲一個真正的變量名稱。 – 2010-08-13 11:26:58

回答

2

我不認爲有足夠的細節在這個問題的答案,因爲你並不表示什麼異常實際上是。

可能值得將.Last()調用替換爲.AsEnumerable()。Last(),因爲這將表明問題是否與Last()完全相同,或者它是否位於查詢中的其他位置。 (A)也許你不能因爲查詢提供者的一些限制而不能做得更快,所以如果你可以避免它,一般不值得做,但是(A)也許你不能這樣做,和(B)嘗試它的結果,看看你是否得到相同的異常會告訴你更多關於你的問題。

+0

它看起來很像將AsEnumerable()方法添加到鏈式作品中。 非常感謝!如果有人能解釋爲什麼,那會很好。 – JonRed 2010-08-13 11:44:47

+0

剛剛通過代碼,它是完美的工作。再次感謝! – JonRed 2010-08-13 11:52:55

+0

'AsEnumerable'「結束」LINQ to * whatever *查詢。查詢的其餘部分(例如'Last')使用LINQ to Objects進行評估。 Jon表示的性能問題是因爲'.AsEnumerable()。Last()'會將整個結果集(所有匹配的'CalendarDetails'對象)讀入內存,並迭代它以獲取最後一個結果集。創建另一個查詢可能更有效率,顛倒'cds'中的順序,然後調用'First';這將只從數據庫中檢索單個記錄。 – 2010-08-13 12:35:22

1

很難在與出病因猜測知道你拋出 的異常,但實際上你可以做到這一切在LINQ所以我想這可能是有價值的信息,供各位

var lastID = cds.Last().CalendarDetailID; 
var work = (from cd in cds 
      let wts = startTime.Date + cd.WorkingTimeStart.Value.TimeOfDay 
      let wtf = startTime.Date + cd.WorkingTimeFinish.Value.TimeOfDay 
      where (lastID == cd.CalendarDetailID) && (finishTime > wtf) 
      select Work(startTime.Date.AddDays(1), finishTime, calendarID)).Sum(); 

(上假設工作可以隱式轉換爲.Sum()可以處理的東西,即那個+ =不是一個自定義操作符)

+0

非常感謝。缺少的代碼是關於使用哪個開始時間的邏輯,但這是一些linq查詢邏輯的一個很好的例子。 – JonRed 2010-08-13 11:47:45

1

您需要告訴我們錯誤/異常是爲了幫助正確,但最常見的原因Last()失敗的原因是IQeryable提供程序不支持它。例如我不認爲LinqToSQL支持Last()

+0

它看起來像Linq不支持它,這就是問題所在。添加AsEnumerable讓我在代碼中超過了這一點;我只需要確保它正在做正確的事情。 – JonRed 2010-08-13 11:48:41

+0

請注意,調用AsEnumerable()會執行expresion樹。如果這是從一百萬行數據庫中獲取數據,它將檢索所有100萬行,然後丟棄除最後一行外的所有行。 – 2010-08-13 11:52:28

+0

謝謝你的擡頭。我期望的最大行數大約是四個,通常是兩個。 – JonRed 2010-08-13 11:53:44

2

看起來Linq不支持Last()IQueryable。你可以這樣做:

List<CalendarDetail> cds; 

    // Find matching day of week 
    // Then for that day, cycle through all working times 

    // Return list of working times in day 
    cds = pr.GetCalDetails(calendarID, startTime.DayOfWeek.GetHashCode()).ToList(); 
3

答案是並不是所有的IQueryable提供者都支持所有的Linq方法。具有SQL後端的IQeuryable提供程序(如LinqToSql或Entity Framework)不支持Last(),因爲SQL本身沒有Last的概念。 Last()不會被翻譯成SQL語句。

在SQL中,正確的做法是適當的訂購記錄(通過標識說明,也許),然後做頂1.所以,這就是我們需要在LINQ to做:

CalendarDetail lastCd = cds.OrderByDescending(cd => cd.CalendarDetailId).First(); 
0

如果您CalendarDetailID是運行數字,你可以使用Max()

相關問題