2014-02-06 71 views
1

我有以下代碼錯誤LINQ到實體日期時間

var dates = query.Select(
       x => DateTime.ParseExact(x.Date, "yyyy-MM", CultureInfo.InvariantCulture)); 

var minDate = dates.Min(x => x); 

但是當我執行,我得到的異常

System.Data.Entity.dll但在用戶代碼中沒有處理

附加信息:LINQ to Entities不識別方法 'System.DateTime ParseExact(System.String,System.String, System.IFormatProvider)'方法,此方法不能將 轉換成商店表達式。

我在做什麼錯?我該如何解決這個問題?

+0

爲什麼你將日期時間值作爲字符串存儲在數據庫中?如果你爲你的值使用適當的類型會容易得多。 – MarcinJuraszek

+0

@MarcinJuraszek其實db包含格式爲「yyyy-MM」的值,但我沒有管理員訪問該數據庫 –

+0

@MarcinJuraszek感謝您的編輯以及您的興趣:) –

回答

2

那麼,錯誤其實很明顯。在Linq中沒有將ParseExact的實體翻譯成SQL。請記住,實體框架在封面下將查詢轉換爲SQL命令或一組命令組。如果EF不知道如何翻譯某些內容,則會引發此錯誤。

一個可能的解決方案,雖然效率不高,但將IQueryable轉換爲IEnumerable,這將允許您執行該語句。

var dates = query.ToList().Select(
      x => DateTime.ParseExact(x.Date, "yyyy-MM", CultureInfo.InvariantCulture)); 
+1

'query.ToList()'將從數據庫中獲取所有數據,而不僅僅是'x.Date'值,這很重要。 – MarcinJuraszek

+1

@MarcinJuraszek - 不知道模式,你不能假定表中有多個列。爲了瞭解他自己的模式並做出適當的修改,我給了提問者信用。 –

+0

是的,我知道這是一種可能性。這就是爲什麼我只是評論而不是downvoting :) – MarcinJuraszek

1

恐怕你不得不從DB DATATIME值的所有string表示加載到內存:

var dates = query.Select(x => x.Date).ToList(); 

並進行分析和分作爲LINQ到對象查詢:

var min = query.Min(x => DateTime.ParseExact(x, "yyyy-MM", CultureInfo.InvariantCulture)); 

如果您的DB已設置屬性,並且x.DateDateTime您可以這樣做:

var dates = query.Select(x => x.Date); 
var min = dates.Min(); 

這將被翻譯成適當的SQL查詢,並讓MIN()由數據庫計算,因此您不必將所有數據提取到應用程序內存中。

+0

非常感謝Marcin。我現在會嘗試 –

+0

ToList會工作,並且沒有任何問題,但如果您實際上不會將它用作List,那麼爲什麼要創建List?數組比列表更高效,因此您應該默認調用ToArray,並且只在需要時調用ToList。 – jmcilhinney

+0

@jmcilhinney我不明白爲什麼'ToArray'會更有效率。也許只有一個事實,即ToList()會在所有記錄加載時縮小分配的數組,當ToList()將在底層數組中保留這些未使用的空間以便將來更快地進行其他插入時。 – MarcinJuraszek

0

LINQ to Entities將您的LINQ查詢轉換爲SQL代碼,然後對數據庫執行該查詢。這意味着您編寫的代碼必須能夠轉換爲SQL代碼。沒有辦法將DateTime.ParseExact轉換爲SQL代碼,因此是例外。您將需要通過調用ToArray來評估一個LINQ to Entities查詢,然後您可以對此執行第二個LINQ to Objects查詢,並且它將理解DateTime.ParseExact。

+0

非常感謝jimcilhinney給你答案。但是,我認爲如果它包含一段代碼,可以更好地支持您的答案:) –

2

如果日期是在DB的格式爲「YYYY-MM」,那麼你可以做基於字符串排序查詢,並將結果轉換爲datetime字符串:

var minDateString = query.Select(x => x.Date).Min(); 
var minDate = DateTime.ParseExact(
    minDateString, 
    "yyyy-MM", 
    CultureInfo.InvariantCulture 
); 

許多系統依賴於「yyyy-MM-dd hh:mm:ss」的自然字符串排序,您可以輕鬆依賴該排序的子集。

+0

非常感謝蒂莫西。 Upvoted爲您提供幫助:) –

+0

@JimBlum從您對其他答案的評論中,您似乎想要做的不僅僅是獲取最低日期。您能否更新您的問題,提供更多關於您需要的詳細信息,以便我可以提供更好的答案?我經常採取兩步驟的過程,減少我的行數,並根據需要獲取儘可能多的原始數據,然後到'.ToList()',然後安全地使用我喜歡的內存集合中的所有非SQL兼容調用。 –