2011-05-17 56 views
3

我陷入了一個奇怪的問題。我有一個CashGameGeneralViewModel類至極看起來像這樣linq查詢中的String.Format

public class CashGameGeneralViewModel 
{ 
    public string Limit { get; set; } 
    public int HandsPlayed { get; set; } 

    public float AmountWon { get; set; } 
} 

這裏是應該返回由某個播放器播放所有手中的方法:

public List<CashGameGeneralViewModel> GetAllHands(string playerToFind) 
    { 
     HoldemHandContext db = new HoldemHandContext(); 
     int playerId = GetPlayerId(playerToFind); 
     var holdemHandResult = (from phh in db.PlayersInHoldemHands 
           from hh in db.HoldemHands 
           where hh.Id == phh.HandPlayed && phh.PlayerId == playerId 
           select new CashGameGeneralViewModel() 
              { 
               Limit = //"some text", 
               String.Format("{0:0.00}", hh.SBlindAmount) + "/" + 
               String.Format("{0:0.00}", hh.BBlindAmount), 
               HandsPlayed = db.HoldemHands.Distinct().Count(), 
               AmountWon = 0 
              } 
           ).ToList(); 

     return holdemHandResult; 
    } 

    public int GetPlayerId(string playerToFind) 
    { 
     HoldemHandContext db = new HoldemHandContext(); 
     int playerId = (from p in db.Players 
         where p.ScreenName == playerToFind 
         select p.Id).FirstOrDefault(); 

     return playerId; 
    } 

現在的問題是

Limit = //"some text", 
String.Format("{0:0.00}", hh.SBlindAmount) + "/" + 
String.Format("{0:0.00}", hh.BBlindAmount) 

部分。 hh.SBlindAmounthh.BBlindAmount是浮點值。我想使用String.Format,因爲0.10被縮短爲0.1,並以字符串格式獲得它,就像我想要的那樣。但我得到一個例外說,'The invocation of the constructor on type 'PokerRecord.View.CashGameGeneralUC' that matches the specified binding constraints threw an exception.' Line number '60' and line position '18'.。當我刪除string.format並放入一些「常規」字符串時,一切正常......任何人都知道爲什麼?

+1

你有應該有ABO更多信息InnerException屬性除外真正的問題。你檢查過了嗎? – Tim 2011-05-17 18:51:21

+0

只是看了起來,現在我有另一個問題...內部異常是'LINQ to Entities不能識別'System.String格式(System.String,System.Object)'方法的方法,並且此方法無法翻譯進入一個商店的表達。「我怎麼能得到字符串格式,因爲我想在這裏? – 2011-05-17 18:54:31

+0

我會嘗試下面的AllenG的答案,看看是否更好。我想LinQ to Entities試圖在其實際處理的查詢中使用string.format函數,而不是在事後處理。 AllenG的方式可能會解決這個問題,我不確定。 – Tim 2011-05-17 18:57:01

回答

1

我剛想到的另一個答案,以及我可能更喜歡這樣做的方式。我想說的只是存儲在視圖模型的原始值,然後改變你的極限性能,只是創建基於這些值的字符串:

public string Limit { get { return string.Format("{0:0.00}/{1:0.00}", SmallBlind, BigBlind); } } 

編輯:

我要添加推理寧願這樣 - 它是非破壞性的。但是如果你的ViewModel不會有太大的改變,或者你知道將來不再需要BigBlind/SmallBlind屬性,那麼這可能是矯枉過正或完全不必要的。

+0

這工作正常......謝謝:) – 2011-05-17 19:07:18

+0

不客氣:) – Tim 2011-05-17 19:08:12

2

我想爲你想要做的事情(格式化一個特定的float到一個字符串),你想要過載.ToString(),它允許你提供一個格式提供者。

喜歡的東西SmallBlind.ToString("{0:0.00}")

你可能會找什麼能最好地表示:根據你得到的錯誤

Limit = string.Format("{0}/{1}", 
      SmallBlind.ToString("{0:0.00}"), 
      BigBlind.ToString("{0:0.00}")), 
//Rest of statement here... 

(昨天我在一個問題一個類似的)這裏的我的解決方案:

Limit = GetLimit(SmallBlind, BigBlind), 
//Rest of Statement Here 

然後用的String.format定義獲取上限:

private string GetLimit(double smallBlind, double bigBlind) 
{ 
    return string.Format("{0}/{1}", 
      smallBlind.ToString("{0:0.00}"), 
      bigBlind.ToString("{0:0.00}")); 
} 

我會把它留給比我更好的專家,爲什麼這會導致Linq出現故障,但是這會讓你感覺到它。

這當然假設您的CashGameGeneralViewModel出於某種原因不應該意識到盲注。如果可能,解決方案(在另一個答案中已經提到)是讓Limit getter返回預先形成的字符串。

可能有更好的方式來做我正在做的事情,但遇到同樣的問題,我就是這樣解決的。

+0

仍然獲得相同的「{」LINQ to Entities不能識別方法'System.String Format(System.String,System.Object,System.Object)'方法,並且此方法不能轉換爲存儲表達式。「} '錯誤:( – 2011-05-17 19:00:16

+0

好吧...我遇到類似的那天,我會用我的解決方案更新我的答案,以解決這個問題... – AllenG 2011-05-17 19:01:28

1

問題是你現在試圖做的與SQL不兼容。您可能需要先獲取臨時對象中的數據,然後執行簡單的轉換才能進入所需的對象。或者,您可能想要將該對象的原始值和另一個屬性僅用於顯示目的,這將以任何您喜歡的格式返回原始值。

1

龍答:

有些事情不從CLR方法TSQL翻譯好。日期格式化是一個很好的例子,因爲.ToString(string s),.ToShort ...等方法依賴於大量特定於語言環境的設置來格式化最終結果。 (分隔符,不同日期部分的順序,使用什麼日曆時間,月/日名稱等)。 T-SQL沒有像.net那樣詳細支持所有特定於區域設置的格式化事項,也沒有其他RDBMS SQL方言。換句話說,將.net方法DateTime.ToShortDateString轉換爲TSQL將導致大量的SQL將所有特定於語言環境的格式因素考慮在內,否則將導致返回與.net不同的結果的方法當量。 (這會更令人困惑)。

爲了說明在.net的日期和時間格式中涉及大量特定於語言環境的邏輯,我在今天的日期的幾種不同的區域/區域設置下包含了DateTime.ToShortDateString和DateTime.ToLongDateString的輸出:

en-us (US English): 
11/15/2010 
Monday, November 15, 2010 

sv-se (Swedish): 
2010-11-15 
den 15 november 2010 

zh-cn (Chinese): 
2010/11/15 
2010年11月15日 

ar-sa (Arabic/Saudi Arabia): 
09/12/31 
09/ذو الحجة/1431 

th-th (Thai): 
15/11/2553 
15 พฤศจิกายน 2553 

是的,這是正確的,所有五個以上例子是相同的日期(2010年11月15日),只有不同的文化/區域設置。想象一下爲此所需的所有日期格式代碼的T-SQL表示的大小。可能不是你想用你的數據庫打... :)

所以要回答你的問題:你最好的選擇是做日期格式和其他東西.net做的不錯,但不能翻譯到.net代碼中的T-SQL。可以在具有格式化屬性的單獨投影類中,或者將L2E查詢投影到.net類型中,然後執行第二個L2O(linq-to-objects)查詢,該查詢投影爲具有格式和其他格式的新類型您可能想要做的轉換。

簡短的回答:

做的兩個步驟 - 一個L2E查詢是否支持L2E部分,和L2O查詢確實日期格式和其他的東西,最好是在.NET代碼來完成。 ..

//Linq-to-entities query to get the fullname, categoryname, and date 
var query = from c in db.Contacts select new { c.FullName, c.Category.CategoryName, c.DateCreated }; 

//Linq-to-objects query (.AsEnumerable will separate the L2E from L2O part) that call date formatting methods and other stuff that isn't supported by L2E 
var r = from c in query.AsEnumerable() select new { c.FullName, c.CategoryName, ShortDate = c.DateCreated.ToString("D") }; 

回答here(MSDN論壇)複製