实体框架十进制截断问题
本文关键字:问题 十进制 框架 实体 | 更新日期: 2023-09-27 17:54:11
我正在做的项目使用实体框架6.0 Code-First。
我的一个同事,由于缺乏EF的经验,手动将数据库上一个字段的字段类型更改为decimal(28,10)
,而不是在DbContext
的OnModelCreating
方法中正确地这样做。实体框架允许他这样做,永远不会在任何未来的迁移中抛出错误。
上周,另一个同事遇到了一个从表中克隆记录的过程的问题,其中新记录中的小数值被截断为小数点后2位(没有四舍五入)。
该克隆的代码类似于以下代码(在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();
}
当我指出,作为一个侧面的观点,Amount
字段是decimal(28,10)
的声明应该在OnModelCreating
中,他继续这样做,并添加了一个迁移。有趣的是,这样做最终解决了上面代码的问题。
我的问题有两个:
- 为什么这个问题不影响原始记录的创建,而只影响克隆?
- 为什么在
OnModelCreating
中添加那行修复它?
谢谢!
如果您最初没有任何精度集,那么代码优先的默认约定是创建精度为18、比例为2的十进制列(因此只有两位小数)。我认为有可能这些记录一开始就被截断了。
另外,默认情况下,SQL Server提供程序的SQL生成器将SqlParameter.Scale
属性设置为模型中定义的比例,除非您将TruncateDecimalsToScale设置为false,否则会影响数据库更新和插入。但是,我不确定这些带有额外小数点的记录是如何在数据库中结束的。
当使用codeFirst与EF时,它在代码(c#或VB)中创建模型,然后它将模型复制到您的DB。
要回答你的问题,我可以说:
- 这个问题一开始没有影响,因为当你创建你的模型时,所有的变化都直接对你的数据库进行了,然后你的表就和模型中的表完全一样了。
请记住,实体框架是一个ORM(对象关系映射器),它为您创建了一组基于领域模型的实体(类)——这个领域模型可以以三种不同的方式存在:代码优先、模型优先和数据库优先。
-
代码优先意味着你通过创建一组类(又名实体)来开始你的项目,这些类将在你的数据库中表示你的关系模型。(你的源是你的类,目标是你的数据库)
-
模型优先意味着您通过使用可视化工具开始您的项目,基本上是拖放,连接点等,这使您可以创建一个模型,该模型将在数据库中表示您的关系模型。(你的源是你的模型,目标是你的数据库)
-
database -first意味着你通过从数据源(通常是数据库)中选择模型来启动你的项目,这种方法将在你的visual studio项目中为你创建一组类(实体)。(你的源是你的数据库,目标是你的代码)
所以,无论你在上述任何场景中做了什么改变,都必须通过实体框架从源复制到目标。
这里发生的事情是你的同事的一个错误,他直接在你的数据库中做了一个更改,但它一定是从你的EF项目中完成的(首先是代码)。
当你调用ClonneAccounts EF所有的魔法(连接到DB,执行查询,获取数据,将其转换为实体类,然后检索它们或反之亦然)->这是当你的应用程序崩溃,因为InvalidCastException
- EF不检查一致性,方案或结构你的表每次调用ClonneAccounts,它只是检索实体和数据库之间的数据和插入/更新数据。如果您想要更新/检查一致性并复制更改,则必须手动执行。这就是为什么直到你在"代码端"修复你的模型并运行工具,它复制所有更改到你的数据库。
希望有所帮助