linq查询中的String.Format

时间:2011-05-17 18:46:21

标签: .net wpf linq entity-framework c#-4.0

我陷入了一个奇怪的问题。我有一个CashGameGeneralViewModel类,看起来像这样

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并输入一些“常规”字符串时,一切正常......任何人都知道为什么?

4 个答案:

答案 0 :(得分:2)

我认为你正在尝试做什么(将特定浮点数格式化为字符串),你想要.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:

定义Get Limit
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返回预先格式化的字符串。

可能有更好的方法来做我正在做的事情,但是,遇到你遇到的同样的问题,这就是我解决它的方式。

答案 1 :(得分:1)

我刚才想到的另一个答案,以及我可能更愿意这样做的方式。我只是将这些原始值存储在ViewModel中,然后将Limit属性更改为仅根据这些值创建字符串:

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

修改

我会用这种方式加入我的推理 - 它是非破坏性的。但是,如果您的ViewModel不会发生太大变化,或者您知道将来永远不需要BigBlind / SmallBlind属性,那么这可能是过度或完全没有必要。

答案 2 :(得分:1)

此问题是您尝试执行的操作与SQL不兼容。您可能需要先在临时对象中获取数据,然后执行简单的转换到所需的对象。或者,您可能希望将该对象的原始值和另一个属性仅用于显示目的,这将以您喜欢的任何格式返回原始值。

答案 3 :(得分:1)

答案很长:

有些东西无法从CLR方法很好地转换为TSQL。日期格式化是一个很好的例子,因为.ToString(string s),. TooShort ......等方法依赖于大量特定于语言环境的设置来格式化最终结果。 (分隔符,不同日期部分的顺序,使用的日历时代,月/日名称等)。 T-SQL没有像.net那样详细支持所有那些特定于语言环境的格式化事物,也没有其他RDBMSes 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论坛)

复制的答案