如何"降级" C#十进制数据类型到一些任意小数位数?

时间:2015-10-02 13:49:08

标签: c# linq entity-framework-4

我有一个数据库表,其中的字段以非常简化的形式定义,如

CREATE TABLE Product
(
    ProductId INT,
    Price SMALLMONEY
)

我有一个LINQ实体框架查询,其简化形式如下:

Iqueryable query = from Product in testDB.Products
        select new
        {
            Price = Product.Price
        }

问题在于,这会在我的其他帖子https://stackoverflow.com/questions/32610246/aspxtextbox-how-to-make-it-to-use-displayformatstring-correctly

中产生意外和不受欢迎的行为

我已经研究了这个并且我得出结论,这个不受欢迎的行为是由于我的查询结果返回字段价格为十进制,带有4个小数点。这是可以理解的,因为SMALLMONEY存储在具有4个小数精度的数据库中。 如果我减少小数的数量一切正常。在这个简单的例子中有类似的东西

Iqueryable query = from Product in testDB.Products
            select new
                {
                    Price = 1.12m;  // Decimal literal with 2 decimals
 }

所以我认为将这个数字四舍五入到两位小数就足够了,我会好的。

Iqueryable query = from Product in testDB.Products
                select new
                {
                    Price = Decimal.Round(Products.Price,2) // round to two decimals    
                }

错误的。不知何故,价值价值持续存储它存储4个小数点的知识,我的网页形式搞砸了。

我查看了在http://referencesource.microsoft.com/#mscorlib/system/decimal.cs

找到的DecimalRound()的源代码
[System.Security.SecuritySafeCritical]  // auto-generated
public static Decimal Round(Decimal d, int decimals)
{
    FCallRound (ref d, decimals);
    return d;
}

这通过引用传递参数值,所以我猜只有参数的值被改变而不是它的内部" meta"描述精度的数据。

我该怎么办?如何将精度降级为两位小数。

2 个答案:

答案 0 :(得分:2)

我怀疑问题是您实际上没有使用}执行舍入。相反,您将在正在转换为SQL的查询中表达它。

如果您希望在.NET中完成舍入,则需要确保使用LINQ to Objects - 最简单的方法是调用decimal.Round。例如:

AsEnumerable

请注意,您应确保在 var results = testDB.Products .Select(p => new { p.Name, p.Price }) .AsEnumerable() .Select(p => new { p.Name, Price = decimal.Round(p.Price, 2) }); 之前进行任何排序,过滤等,以避免将所有结果拉下来并在本地过滤。

作为旁注,虽然没有简单的属性来获取比例,符号和有效数,但您可以使用decimal.GetBits(decimal)来获取内部表示。这对于比较两个值是否相同非常有用,有关详细信息,请参阅文档,了解每个位的含义。

答案 1 :(得分:0)

如果没有更多的上下文,可以建议的是转换为不同的数据类型:

select new 
{
    Price = (double) Products.Price
};

或字符串:

select new
{
    Price = Products.Price.ToString("##.00")
}