2011-04-26 50 views
10

我最近已將此代碼遷移到實體框架4並且失敗。顯然,如果狀態沒有值,則返回所有匹配,如果它具有與user.StatusID == 1相匹配的值。實體框架中的簡單條件LINQ查詢4

return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password && 
       (!status.HasValue || user.StatusID == 1) 
       ); 

異常返回:

ArgumentException: The specified value is not an instance of type 'Edm.Int32' 
Parameter name: value 

但是,移除條件測試,它工作正常:

return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password && 
       user.StatusID == 1 
       ); 

任何想法?如何在EF 4中執行條件測試?當然,如果線條不分開?我在Linq to Sql中一次又一次地使用這些條件測試;對於EF 4中不起作用的原因真的很奇怪。一定有一些簡單的錯誤,或許在EF 4.0中有一個推薦的替代方法。

感謝您的幫助球員,
格雷厄姆

+0

什麼'Edm.Int32'?是你自己實現的'System.Int32'嗎? – Stecya 2011-04-26 11:12:23

+1

@Stecya:http://msdn.microsoft.com/en-us/library/bb387164.aspx,似乎是EF的一些內部特徵。 – Euphoric 2011-04-26 11:14:05

回答

5

好吧,我解決了兩件事的結合。

  1. 做一個簡單的空測試。
  2. 檢測本地鑄件status變量沒有.Value方法。

兩者都必須到位,否則它將繼續失敗,並出現錯誤!這將是很好的測試值屬性,但我想查詢必須非常簡單 - 非常有趣!

return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password && 
       (status == null || user.StatusID == (int) status) 
       ); 

我將等待更好的實現,否則接受我自己的答案。但感謝大家的幫助。

+0

EF看起來越來越好...感謝您的解決方案,它今天咬我一口。 – greenoldman 2011-08-04 09:14:02

0

是什麼status.HasValue?如果狀態是User一個領域,你應該這樣稱呼它:user.status.HasValue

如此簡單的做到這些:

if(status.HasValue) 
    return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password && 
       user.StatusID == 1 
       ); 

    return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password 
       ); 
+0

嗨Farzin,它是一個可以爲空的int,而不是封閉方法的一個字段。編輯 – GONeale 2011-04-26 11:04:17

+0

,我知道這不是一個常用的解決方案,但適合你! ;) – 2011-04-26 11:08:37

+0

Eek,維護兩個查詢。不,謝謝,但無論如何感謝=) – GONeale 2011-04-26 11:10:26

0

我想你應該附上user.StatusID == 1組附加括號的,因爲我認爲目前EF試圖應用||操作狀態.HasValue和user.StatusId,然後將結果與1進行比較。

+0

唉,沒有運氣。雖然好想法。 – GONeale 2011-04-26 11:05:52

2

如何爲!status.HasValue創建單獨的變量並在查詢中使用它?

我想這裏的問題是,EF試圖將您的狀態變量作爲參數傳遞到查詢中,然後在SQL本身中執行邏輯。嘗試檢查生成的SQL是什麼。

+0

哇,通過,聲明'var test =!status.HasValue'然後測試測試。但它不好。然而,它讓我嘗試了我能想到的每一個投射和包圍技巧,因爲如果它像這樣工作,它可以在線工作,它們都解決錯誤。哼。還有什麼想法? – GONeale 2011-04-26 11:14:44

+0

我認爲問題在於'status'不是int;並且它在一個構造中比較一個枚舉和一個int類型時感到困惑。沒有鑄件可以工作,因爲它是可空的:( – GONeale 2011-04-26 11:17:51

2

在where子句中執行空檢查的另一種方法是分離出可選參數並只在需要時才應用它。

例如

var data = users.Where(
     user => 
      user.Username == username && 
      user.EncryptedPassword == password 
     ); 

    if (status.HasValue) 
    { 
     data = data.Where(user => user.StatusID == status.Value); 
    } 

    return data.FirstOrDefault(); 

我不認爲它會提供比目前的解決方案,而不是多一點的可讀性。

+0

感謝您的想法 – GONeale 2011-04-27 06:02:40

0

在第一galance它在我的腦海appeare這樣的:

return users.SingleOrDefault(
       user => 
       user.Username == username && 
       user.EncryptedPassword == password && 
       (status == null || user.StatusID == 1) 
       ); 

,但是當我看它更多的我覺得這是錯了,所以怎麼樣?

return users.SingleOrDefault(
    user => 
    user.Username == username && 
    user.EncryptedPassword == password && 
    status != null && 
    user.StatusID == 1) 
); 

背後它究竟是什麼商業邏輯?

+0

啊,好吧,您的第二個查詢將始終強制一個狀態不一定是這樣的,'status'可能是'null',在這種情況下,我想獲取所有的條目,這就是爲什麼我使用'||'操作符 – GONeale 2011-04-27 06:04:15

1

好像你已經找到了解決辦法...

然而,僅供參考......我有在VS以下行沒有問題2010

Nullable<int> status = 0; 
    String username = "Alexandre 2"; 

    var test = _context.Contacts.SingleOrDefault(c => c.FirstName == username && (!status.HasValue || c.ContactID == 1)); 

我沒有得到任何錯誤,聯繫對象我期望是返回...所以如果有的話,這讓我想知道什麼是你的用戶類型.StatusID字段?

祝你好運

+0

這是EF4嗎? – GONeale 2011-04-27 06:02:12