简体   繁体   English

实体框架十进制截断问题

[英]Entity Framework Decimal Truncation Issue

The project I'm working on uses Entity Framework 6.0 Code-First. 我正在研究的项目使用Entity Framework 6.0 Code-First。

One of my co-workers, due to his lack of experience with EF, manually changed the field type of a field on the database to being decimal(28,10) , instead of doing it the correct way in the OnModelCreating method of DbContext . 我的一位同事由于缺乏EF经验,因此手动将数据库中字段的字段类型更改为decimal(28,10) ,而不是使用OnModelCreating方法进行正确的DbContext Entity Framework allowed him to do so, never throwing an error upon any future migrations. Entity Framework允许他这样做,以后再也不会出错。

Last week, another co-worker was running into a problem with a process that clones records from that table, where the decimal values in the new records were being truncated to 2 decimal places (with no rounding occurring). 上周,另一个同事遇到了一个问题,该过程从该表克隆记录,在该表中,新记录中的十进制值被截断为两位小数位(没有四舍五入)。

The code for that cloning resembles the following (using the Repository pattern on top of EF): 该克隆的代码类似于以下代码(使用EF之上的Repository模式):

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

When I pointed out, as a side-point, that the declaration of the Amount field being decimal(28,10) should really be in OnModelCreating , he went ahead and did that, and added a migration. OnModelCreating ,当我指出Amount字段的声明为decimal(28,10) ,实际上应该在OnModelCreating ,他继续这样做,并添加了迁移。 Doing that, interestingly enough, ended up solving the issue with the code above. 有趣的是,这样做最终解决了以上代码的问题。

My question is two-fold: 我的问题有两个:

  1. Why did that issue not affect the creation of the original records as well, and only upon cloning? 为什么该问题也不会仅在克隆时也不会影响原始记录的创建?
  2. Why did adding that line in OnModelCreating fix it? 为什么在OnModelCreating添加该行OnModelCreating解决该问题?

Thanks! 谢谢!

If you didn't originally have any precision set, the default convention for code-first is to create decimal columns with precision of 18 and scale of 2 (so only two decimal places). 如果最初没有设置任何精度,则代码优先的默认约定是创建精度为18且小数位数为2 (因此只有两个小数位)的十进制列。 I think it's possible the records had originally been truncated in the first place. 我认为记录最初可能已被截断。

Also, by default, the SQL Server provider's SQL generator sets SqlParameter.Scale property to the scale defined in the model, unless you had TruncateDecimalsToScale set to false, which would affect database updates and inserts. 同样,默认情况下,除非您将TruncateDecimalsToScale设置为false,否则SQL Server提供程序的SQL生成器SqlParameter.Scale属性设置为模型中定义的比例,这会影响数据库更新和插入。 I'm not sure how those records with additional decimal places ended up in the database, though. 但是,我不确定那些带有其他小数位的记录如何最终存储在数据库中。

When using codeFirst with EF it creates the model in code (C# or VB), then it replicates the model to your DB. 当使用带EF的codeFirst时,它将在代码(C#或VB)中创建模型,然后将模型复制到数据库中。

To answer your questions I could say that: 为了回答您的问题,我可以这样说:

  1. The issue did't affect at first because when you created your model all the changes were made directly to your DB, then you had your tables exactly the same as in the model. 最初,该问题没有影响,因为在创建模型时,所有更改都直接对数据库进行,然后您的表与模型中的表完全相同。

Remember that Entity Framework is an ORM (Object Relational Mapper) it creates, for you and with little effort, a set of entities (classes) based on a domain model -- this domain model can exists it three different flavours: code-first, model-first, and database-first. 请记住,实体框架是一个ORM(对象关系映射器),它为您轻松创建了基于域模型的一组实体(类),该域模型可以以三种不同的方式存在:代码优先,模型优先,数据库优先。

  • Code-first means that you start your project by creating a set of classes (aKa Entities) which will represent your relational model in your data base. 代码优先意味着您可以通过创建一组类(aKa实体)来启动项目,这些类将在数据库中表示您的关系模型。 (your source will be your classes and the target your database). (您的源将是您的类,而目标将是您的数据库)。

  • Model-first means that you start your project by using a visual tool, basically drag and drop, connecting points and so on, which lets you create a model which will represent your relational model in your data base. “模型优先”意味着您可以使用可视化工具(基本上是拖放,连接点等)来启动项目,从而可以创建一个模型,该模型将在数据库中表示您的关系模型。 (your source will be your model and the target your database). (您的源将是您的模型,目标是您的数据库)。

  • Database-first means that you start your project by selecting the model from a data source (usually a database), this approach will create for you a set of classes (Entities) in your visual studio project. 数据库优先意味着您通过从数据源(通常是数据库)中选择模型来启动项目,这种方法将为您在Visual Studio项目中创建一组类(实体)。 (your source will be your database and the target your code). (您的源将是您的数据库,目标是您的代码)。

So, whatever change you make in any of the above scenarios must be replicated from source to target via Entity Framework. 因此,您在上述任何情况下所做的任何更改都必须通过Entity Framework从源复制到目标。

What happened here was a mistake from your co-worker, who made a change directly in your database, but it must had been done from your EF project (code first). 这里发生的是您同事的一个错误,他直接在您的数据库中进行了更改,但这必须是从您的EF项目中完成的(代码优先)。

When you invoked ClonneAccounts EF made all the magic (connect to DB, execute a query, gets data, cast it to your entity classes, and then retrieve them or visceversa) --> this is when your app crashed because of an InvalidCastException. 当您调用ClonneAccounts时,EF发挥了所有魔力(连接到数据库,执行查询,获取数据,将其强制转换为您的实体类,然后检索它们或访问visceversa)->这是您的应用由于InvalidCastException而崩溃的时候。

  1. EF does not check consistency, scheme or structure of your tables every time you invoke ClonneAccounts, it just retrieves data between Entities and Database and insert/update data. EF不会在每次调用ClonneAccounts时检查表的一致性,方案或结构,它只是在Entities和Database之间检索数据并插入/更新数据。 If you want to update/check consistency and replicate changes you have to do it manually. 如果要更新/检查一致性并复制更改,则必须手动进行。 That is why until you fixed your model in the "code side" and ran the tool it replicated all changes to your db. 这就是为什么直到您在“代码端”中修复模型并运行该工具后,该工具才能将所有更改复制到您的数据库。

Hope it helps 希望能帮助到你

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM