C#/TSQL十进制边界检查-有更干净的方法吗?

C#/TSQL十进制边界检查-有更干净的方法吗?,c#,tsql,refactoring,decimal,code-cleanup,C#,Tsql,Refactoring,Decimal,Code Cleanup,我写了一个快速的c#扩展方法,但不确定是否有更干净的方法来完成我想做的事情。它确实可以工作,但使用字符串转发器和插入小数点让人感觉有点不舒服 目标是在应用程序级别,我们可以在发送到数据库之前清除/修复任何数据问题,以防止溢出 注意:在这种情况下,PCL库不能引用DLL之外的内容 因此,您可以通过执行(10^p-1)*(10^-s)来获得上界和下界,从而完全消除重复的hacky字符串 如果要检查以确保缩放不会被截断,可以实际截断它,然后比较值。如果截断值和原始值相同,则比例有效 综合起来,你会得到

我写了一个快速的c#扩展方法,但不确定是否有更干净的方法来完成我想做的事情。它确实可以工作,但使用字符串转发器和插入小数点让人感觉有点不舒服

目标是在应用程序级别,我们可以在发送到数据库之前清除/修复任何数据问题,以防止溢出

注意:在这种情况下,PCL库不能引用DLL之外的内容


因此,您可以通过执行
(10^p-1)*(10^-s)
来获得上界和下界,从而完全消除重复的hacky字符串

如果要检查以确保缩放不会被截断,可以实际截断它,然后比较值。如果截断值和原始值相同,则比例有效

综合起来,你会得到这样的结果:

public static bool TsqlDecimalBoundariesCheck(this decimal valueToCheck, int precision, int scale)
{
    if (scale > precision) throw new ArgumentException($"BOUNDARY CHECK: Scale [{scale}] must not be higher than Percision [{precision}]");

    //Upper/lower bounds 
    var step = (decimal)Math.Pow(10, precision);
    var upperBoundry = (step - 1) * (decimal)Math.Pow(10, -scale);
    var lowerBoundry = -1 * upperBoundry;

    //Truncate decimal to scale   
    //If the truncated value does not equal the original, it must've been out of scale
    step = (decimal)Math.Pow(10, scale);
    var truncated = Math.Truncate(step * valueToCheck) / step;

    return (valueToCheck <= upperBoundry)
        && (valueToCheck >= lowerBoundry)
        && truncated == valueToCheck;
}
public static bool tsqldicimalboundariescheck(此十进制值用于检查,整数精度,整数刻度)
{
if(scale>precision)抛出新的ArgumentException($“边界检查:scale[{scale}]不能高于Percision[{precision}]”);
//上界/下界
var步长=(十进制)数学功率(10,精度);
var上限=(步骤-1)*(十进制)数学功率(10,-标度);
var lowerBoundry=-1*上限;
//按比例截断小数
//如果截断的值不等于原始值,则它一定超出了比例
步长=(十进制)数学功率(10,刻度);
var truncated=Math.Truncate(步骤*valueToCheck)/step;
返回值(valueToCheck=lowerBoundry)
&&截断==值检查;
}

因此,通过执行
(10^p-1)*(10^-s)
来获得上限和下限,您肯定可以摆脱重复的黑字符串

如果要检查以确保缩放不会被截断,可以实际截断它,然后比较值。如果截断值和原始值相同,则比例有效

综合起来,你会得到这样的结果:

public static bool TsqlDecimalBoundariesCheck(this decimal valueToCheck, int precision, int scale)
{
    if (scale > precision) throw new ArgumentException($"BOUNDARY CHECK: Scale [{scale}] must not be higher than Percision [{precision}]");

    //Upper/lower bounds 
    var step = (decimal)Math.Pow(10, precision);
    var upperBoundry = (step - 1) * (decimal)Math.Pow(10, -scale);
    var lowerBoundry = -1 * upperBoundry;

    //Truncate decimal to scale   
    //If the truncated value does not equal the original, it must've been out of scale
    step = (decimal)Math.Pow(10, scale);
    var truncated = Math.Truncate(step * valueToCheck) / step;

    return (valueToCheck <= upperBoundry)
        && (valueToCheck >= lowerBoundry)
        && truncated == valueToCheck;
}
public static bool tsqldicimalboundariescheck(此十进制值用于检查,整数精度,整数刻度)
{
if(scale>precision)抛出新的ArgumentException($“边界检查:scale[{scale}]不能高于Percision[{precision}]”);
//上界/下界
var步长=(十进制)数学功率(10,精度);
var上限=(步骤-1)*(十进制)数学功率(10,-标度);
var lowerBoundry=-1*上限;
//按比例截断小数
//如果截断的值不等于原始值,则它一定超出了比例
步长=(十进制)数学功率(10,刻度);
var truncated=Math.Truncate(步骤*valueToCheck)/step;
返回值(valueToCheck=lowerBoundry)
&&截断==值检查;
}

1000米的
1000m
测试是重复的,您输入的
精度一致。:)再见,谢谢。。是的,可怕的拼写者。。据我所知,大多数开发人员都是这样。谢谢你的帮助。为什么VS还没有添加拼写检查;)@MrZander——谢谢你,我应该提到这是在一个没有任何外部引用的PCL库中,它没有访问该名称空间的权限。但如果有人需要,这是一个很好的解决方案。看起来像是一份工作。
1000m
测试是重复的,并且您会一致地键入
精度。:)再见,谢谢。。是的,可怕的拼写者。。据我所知,大多数开发人员都是这样。谢谢你的帮助。为什么VS还没有添加拼写检查;)@MrZander——谢谢你,我应该提到这是在一个没有任何外部引用的PCL库中,它没有访问该名称空间的权限。但是如果有人需要的话,这是一个很好的解决方案。看起来像是一份工作。这确实是一个非常干净的方法来执行比例,但是研究我的用例,舍入是可以接受的,但是100%是关于更重要的是什么,强制执行比例还是接受舍入值的一个很好的观点。在999.09的情况下,该值仍然在SQL中的TSQL十进制(4,1)范围内,但将导致存储四舍五入值999.1。最后,根据我写问题的方式,我认为你的回答仍然回答了这个问题,即使它不能完全解决我的问题,这将允许四舍五入。@traviswhiden谢谢!至少,您可以去掉截断检查,函数将以与您当前工作相同的方式执行,只需不进行字符串操作。这确实是一种非常干净的方式来强制执行比例,但研究我的用例,舍入是可以接受的,但100%是关于更重要的方面的一个很好的观点,强制执行比例或接受舍入值。在999.09的情况下,该值仍然在SQL中的TSQL十进制(4,1)范围内,但将导致存储四舍五入值999.1。最后,根据我写问题的方式,我认为你的回答仍然回答了这个问题,即使它不能完全解决我的问题,这将允许四舍五入。@traviswhiden谢谢!至少,您可以去掉截断检查,函数将以与您当前工作相同的方式执行,只是不需要字符串操作。
public static bool TsqlDecimalBoundariesCheck(this decimal valueToCheck, int precision, int scale)
{
    if (scale > precision) throw new ArgumentException($"BOUNDARY CHECK: Scale [{scale}] must not be higher than Percision [{precision}]");

    //Upper/lower bounds 
    var step = (decimal)Math.Pow(10, precision);
    var upperBoundry = (step - 1) * (decimal)Math.Pow(10, -scale);
    var lowerBoundry = -1 * upperBoundry;

    //Truncate decimal to scale   
    //If the truncated value does not equal the original, it must've been out of scale
    step = (decimal)Math.Pow(10, scale);
    var truncated = Math.Truncate(step * valueToCheck) / step;

    return (valueToCheck <= upperBoundry)
        && (valueToCheck >= lowerBoundry)
        && truncated == valueToCheck;
}