linq 查询中的 String.Format

发布于 2024-11-07 16:18:22 字数 2200 浏览 0 评论 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 并且使用字符串格式我得到了我想要的。但我收到一个例外,上面写着:

“对与指定绑定约束匹配的类型“PokerRecord.View.CashGameGeneralUC”的构造函数的调用引发了异常。”行号“60”和行位置“18”。

当我删除 string.format 并放入一些“常规”字符串时,一切正常......有人知道为什么吗?

I am stuck on a weird problem. I have a CashGameGeneralViewModel class which looks like this

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

    public float AmountWon { get; set; }
}

Here is the method that should return all hands played by a certain player:

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;
    }

The problem now is the

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

part. hh.SBlindAmount and hh.BBlindAmount are float values. I wanted to use String.Format because 0.10 is shortened to 0.1 and with the string format I got it like I want it. But I am getting an exception which says:

'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'.

When I remove the string.format and put in some "regular" string everything works fine... Anyone knows why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

謌踐踏愛綪 2024-11-14 16:18:22

我认为对于您想要执行的操作(将特定浮点数格式化为字符串),您需要重载 .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 返回预先格式化的字符串。

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

I think for what you're trying to do (format a specific float into a string) you want the overload of .ToString() which allows you to provide a format provider.

Something like SmallBlind.ToString("{0:0.00}")

What you're probably looking for might best be represented:

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

Based on the error you're getting (I got a similar one in a problem yesterday) here's my solution:

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

Then define Get Limit with the string.Format:

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

I'll leave it to better experts than I on WHY that's causing a failure in Linq, but that should get you around it.

This, of course, assumes that your CashGameGeneralViewModel should not be aware of the Blinds for some reason. If it can be, the solution (already mentioned in another answer) is to have the Limit getter return the pre-formated string.

There may be a better way to do what I'm doing, but, running into the same problem you've got, that's how I solved it.

日暮斜阳 2024-11-14 16:18:22

我刚刚想到的另一个答案,以及我可能更喜欢的方式。我想说只需将这些原始值存储在 ViewModel 中,然后更改您的 Limit 属性以仅根据这些值创建字符串:

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

编辑:

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

Another answer I just thought of, and the way I'd probably prefer to do it. I'd say just store those original values in the ViewModel and then change your Limit property to just create the string based on those values:

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

Edit:

I'll add my reasoning for preferring it this way - it's non-destructive. But that may be overkill or completely unnecessary if your ViewModel isn't going to change much or you know you'll never need the BigBlind/SmallBlind properties in the future.

酷到爆炸 2024-11-14 16:18:22

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

The problem is what you are trying to do is not compatible with SQL at this moment. You might need to get the data in temporary objects first and then perform simple conversion into the object you want. Or, you might want to have the original value and another property of that object for display purposes only, which will return the original value in any format you like.

只想待在家 2024-11-14 16:18:22

长答案:

有些事情不能很好地从 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 做得很好但无法转换为 T-SQL 的事情在.net代码中。或者在具有执行格式化属性的单独投影类中,或者通过将 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") };

< strong>从此处复制的答案(msdn 论坛)

Long answer:

Some things don't translate well from CLR methods to TSQL. Date formatting is a good example since the .ToString(string s), .ToShort... etc methods rely on a whole lot of locale-specific settings to format the end-result. (Separators, order of the different date portions, what calendar era is used, month/day names etc). T-SQL doesn't have all those locale specific formatting things supported in detail like .net has, nor does other RDBMSes SQL dialects. In other words, translating the .net method DateTime.ToShortDateString into TSQL would result in a very large chunk of SQL to take all the locale-specific formatting factors into account, or alternatively would result in a method returning a different result than the .net equivalent. (Which would be even more confusing).

To illustrate that a fair amount of locale-specific logic is involved in .net's date and time formatting, I have included the output of DateTime.ToShortDateString and DateTime.ToLongDateString under a couple of different culture/locale settings for today's date:

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

Yes, that's right, all five examples above are the same date (15 November 2010) with just different culture/locale settings. Imagine the size of the T-SQL representation of all the date formatting code needed to do that. Probably not something you would want to hit your database with... :)

So to answer your question: Your best bet is to do the date formatting and other things that .net does good but that can't be translated to T-SQL in .net code. Either in a separate projection class that has a property that do the formatting, or by projecting the L2E query into .net types and then do a second L2O (linq-to-objects) query that project into a new type with the formatting and other transformations you may want to do.

Short answer:

Do it in two steps - one L2E query that does the L2E supported part, and a L2O query that does the date formatting and other stuff that is best done in .net code...

//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") };

Answer copied from here (msdn forum)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文