如何使 c# 小数匹配 SQL 小数以进行 EF 更改跟踪?

How can I make a c# decimal match a SQL decimal for EF change tracking?

为避免触及 EF 中不变的记录,原始实体值与当前实体值匹配很重要。我看到一个小数问题,其中 EF 实体具有 SQL 表示形式,并且正在与 c# decimal.

进行比较

这是检测到更改的实体的调试输出。这很清楚地说明了问题。即使实体和源数据都是十进制类型,即使它们相等,这些值也被认为是不同的。

在使用 c# decimal 时如何确保原始值和当前值匹配?

也许有办法在更新前将 c# 小数转换为实体 (SQL) 小数?

另一个例子

我希望截断忽略传入精度高于 SQL 比例

的事实

这个答案不应该完全解决您遇到的问题,而是解决它。

我建议在更高的应用程序层上编写决定是否需要保存对象的逻辑(在这方面,我认为 EF 生成的 classes 是低级对象)。

检索和存储数据的代码可以在存储库 class 中实现,即管理数据访问逻辑的 class。因此,您的应用程序使用的是此存储库 class 而不是 EF 代码。存储库 class 是否在内部使用 EF 或其他东西对您的应用程序不再重要。 如果您为存储库定义了一个接口 class,您甚至可以轻松地用某些技术替换它来保存和检索数据。

有关存储库模式的 Microsoft 文章,请参阅 hereThis 是来自 Whosebug 上的一个问题的信息。

我通常不建议在普通应用程序代码中使用 EF 生成的 classes。一开始可能很诱人,但以后也会像您的情况一样引起问题。

您可以实现一个 proxy-property 来处理从 code-precision 到 db-precision 的转换:

public class MoneyClass
{
    [Column("Money")]
    public decimal MyDbValue { get; set; } // You existing db-property

    [NotMapped]
    public decimal MyCodeValue // some property to access within you code
    {
        get
        {
            return this.MyDbValue;
        }
        set
        {
            decimal newDbValue = decimal.Round(value, 2);
            if (this.MyDbValue != newDbValue)
            {
                Console.WriteLine("Change! Old: {0}, New: {1}, Input: {2}", this.MyDbValue, newDbValue, value);
                this.MyDbValue = newDbValue;
            }
        }
    }
}

static void Main(params string[] args)
{
    MoneyClass dbObj = new MoneyClass()
    {
        MyCodeValue = 123.456M
    };

    Console.WriteLine(dbObj.MyDbValue);
    dbObj.MyCodeValue = 123.457M; // won't change anything
    Console.WriteLine(dbObj.MyDbValue);
    dbObj.MyCodeValue = 123.454M; // will change because of 3rd decimal value 4
    Console.WriteLine(dbObj.MyDbValue);
    dbObj.MyCodeValue = 123.46M; // will change
    Console.WriteLine(dbObj.MyDbValue);
}