实体框架十进制截断问题

时间:2015-06-08 16:02:42

标签: c# entity-framework ef-code-first decimal entity-framework-6

我正在开发的项目使用Entity Framework 6.0 Code-First。

由于他缺乏EF经验,我的一位同事手动将数据库中字段的字段类型更改为decimal(28,10),而不是在{{1}中正确地执行此操作} OnModelCreating的方法。实体框架允许他这样做,从未在任何未来的迁移中抛出错误。

上周,另一位同事遇到了一个问题,该进程克隆了该表中的记录,其中新记录中的十进制值被截断为2位小数(没有发生舍入)。

该克隆的代码类似于以下内容(使用EF顶部的Repository模式):

DbContext

当我指出,作为一个侧点,public void CloneAccounts(List<Account> accounts, int newQuarterID) { var newAccounts = new List<Account>(); accounts.ForEach(account => { var clonedAccount = new Account { QuarterID = newQuarterID AccountName = account.AccountName, AccountNumber = account.AccountNumber, Amount = account.Amount }; newAccounts.Add(clonedAccount); }); AccountRepository.AddMany(newAccounts); AccountRepository.Save(); } 字段Amount的声明真的应该在decimal(28,10)时,他继续这样做,并添加了迁移。有趣的是,这样做最终解决了上述代码的问题。

我的问题是双重的:

  1. 为什么这个问题也不会影响原始记录的创建,只有在克隆时?
  2. 为什么在OnModelCreating中添加该行修复它?
  3. 谢谢!

2 个答案:

答案 0 :(得分:0)

如果您最初没有任何精度集,则代码优先的默认约定是使用precision of 18 and scale of 2创建十进制列(因此只有两位小数)。我认为这些记录最初可能被截断了。

此外,默认情况下,SQL Server提供程序的SQL生成器将SqlParameter.Scale属性设置为模型中定义的比例,除非您将TruncateDecimalsToScale设置为false,这将影响数据库更新和插入。我不确定那些带有额外小数位的记录是如何在数据库中结束的。

答案 1 :(得分:-1)

将codeFirst与EF一起使用时,它会在代码(C#或VB)中创建模型,然后将模型复制到数据库中。

要回答你的问题我可以说:

  1. 这个问题一开始并没有影响,因为当您创建模型时,所有更改都直接发送到您的数据库,那么您的表格与模型中的表格完全相同。
  2. 请记住,Entity Framework是一个ORM(对象关系映射器),它为您创建一个基于域模型的一组实体(类) - 这个域模型可以存在三种不同的风格:代码 - 首先,模型优先,数据库优先。

    • 代码优先意味着您可以通过创建一组类(aKa实体)来启动项目,这些类将代表数据库中的关系模型。 (您的来源将是您的类,目标是您的数据库)。

    • 模型优先意味着您可以使用可视化工具启动项目,基本上是拖放,连接点等,这样您就可以创建一个模型来表示数据库中的关系模型。 (您的来源将是您的模型,目标是您的数据库)。

    • 数据库优先意味着您通过从数据源(通常是数据库)中选择模型来启动项目,此方法将为您在visual studio项目中创建一组类(实体)。 (您的来源将是您的数据库,目标是您的代码)。

    因此,无论您在上述任何场景中所做的任何更改都必须通过Entity Framework从源代码复制到目标。

    这里发生的是你的同事的错误,他直接在你的数据库中进行了更改,但它必须是从你的EF项目(代码优先)完成的。

    当您调用ClonneAccounts时,EF制作了所有魔法(连接到数据库,执行查询,获取数据,将其强制转换为实体类,然后检索它们或内容) - &gt;这是因为InvalidCastException导致您的应用程序崩溃。

    1. 每次调用ClonneAccounts时,EF都不会检查表的一致性,方案或结构,它只是在实体和数据库之间检索数据并插入/更新数据。如果要更新/检查一致性并复制更改,则必须手动执行。这就是为什么在你修改模型“代码端”并运行工具之前,它会将所有更改复制到你的数据库。
    2. 希望有所帮助