2011-05-17 47 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论坛)复制