不需要的小数截断
Posted
技术标签:
【中文标题】不需要的小数截断【英文标题】:Unwanted Decimal Truncation 【发布时间】:2013-05-31 12:44:47 【问题描述】:我的模特:
public class Product
...
public decimal Fineness get; set;
...
为数据库播种:
new List<Product>
new Product ..., Fineness = 0.757M, ... ,
new Product ..., Fineness = 0.674M, ... ,
new Product ..., Fineness = 0.475M, ...
.ForEach(p => context.Products.Add(p));
查询数据库以测试播种:
var products = db.Products.ToList();
foreach (var p in products)
S.D.Debug.WriteLine("ProductList: 0, 1", p.Name, p.Fineness);
控制台输出:
ProductList: Test Product, 0.75
ProductList: Test Product, 0.67
ProductList: Test Product, 0.47
我是在做傻事还是什么???所有内容都被截断到小数点后 2 位。
解决方案 - 感谢 Patrick:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
modelBuilder.Entity<Product>().Property(x => x.Fineness).HasPrecision(10, 5);
【问题讨论】:
你在Entity Framework上配置精度了吗? @PatrickMagee - 得到了解决方案。谢谢你。查看有问题的更新。 @Gravy 应该让 Patrick Magee 将其发布为答案,以便您接受;) Decimal precision and scale in EF Code First 的可能重复项 【参考方案1】:所以您已经定义了标准实体模型,这里是带有 id 和小数的产品,以及您需要的任何其他内容等。
public class Product
public int Id get; set;
public decimal Fineness get; set;
所以我定义了一个初始化程序,在这种情况下,数据库将删除并重新创建我提供的任何种子信息,每次我运行并执行我的应用程序时,都会调用它。
public class Initializer : DropCreateDatabaseAlways<Context>
protected override void Seed(Context context)
// note how I am specifying it here as 4 digits after the decimal point
// and for the second one, 3 digits
// this is where EF precision must be configured so you can expect
// the values you tell EF to save to the db
context.Products.Add(new Product() Id = 1, Fineness = 145.2442m);
context.Products.Add(new Product() Id = 2, Fineness = 12.341m);
public class Context : DbContext
public IDbSet<Product> Products get; set;
public Context()
// I always explicitly define how my EF should run, but this is not needed for the answer I am providing you
Configuration.AutoDetectChangesEnabled = true;
Configuration.ProxyCreationEnabled = true;
Configuration.LazyLoadingEnabled = true;
Configuration.ValidateOnSaveEnabled = true;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
// so here, I am override the model configuration which is what
// EF can use in order to set-up the behaviour of how everything
// is configured in the database, from associations between
// multiple entities and property validation, Null-able, Precision, required fields etc
modelBuilder.Configurations.Add(new ProductConfiguration());
public class ProductConfiguration : EntityTypeConfiguration<Product>
public ProductConfiguration()
ToTable("Product");
HasKey(x => x.Id).Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
// HAS PRECISION.
// Enforces how the value is to be stored in the database
// Here you can see I set a scale of 3, that's 3 digits after
// the decimal. Notice how in my seed method, I gave a product 4 digits!
// That means it will NOT save the product with the other trailing digits.
Property(x => x.Fineness).HasPrecision(precision: 10, scale: 3);
使用 SQL Server 对象资源管理器,我可以查看我制作的 localdb 示例产品,以了解 EF 如何配置我的数据库。
[TestFixture]
public class Tests
[Test]
public void Test()
Database.SetInitializer(new Initializer());
using (var ctx = new Context())
// assert our findings that it is indeed not what we actually specified in the seed method, because of our Entity configuration with HasPrecision.
Product product1 = ctx.Products.Find(1);
Assert.AreEqual(145.244m, product1.Fineness);
Product product2 = ctx.Products.Find(2);
Assert.AreEqual(12.341m, product2.Fineness);
所以我们需要确保数据库知道它应该如何存储我们的十进制值,通过使用实体框架的模型构建器配置来配置我们的实体,通过使用FluentApi
,我们可以通过EntityTypeConfiguration<T>
设置属性特征.
【讨论】:
这是一个了不起的解释。但是,只需将以下内容添加到映射属性(就在 LINQ 查询之后)帮助解决了我非常相似的问题:.HasPrecision(precision: 10, scale: 3);
【参考方案2】:
你不需要EntityTypeConfiguration
,你可以简单地这样做:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
modelBuilder.Entity<Product>().Property(x => x.Fineness).HasPrecision(10, 3);
base.OnModelCreating(modelBuilder);
如果您想更改每个 decimal
的精度和比例,您可以这样做:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
modelBuilder.Conventions.Remove<DecimalPropertyConvention>();
modelBuilder.Conventions.Add(new DecimalPropertyConvention(10, 3));
如果您希望 Decimal (10,3)
将 Fineness = 0.7577m
舍入为 0.758
而不是将 0.757
保存到数据库中,请查看下面的答案。它还解释了为什么 Entity Framework 6.X 默认截断十进制值而不是四舍五入。
https://***.com/a/57095584/3850405
【讨论】:
【参考方案3】:这是很好的tutorial 用于格式化十进制数字
D.Debug.WriteLine("ProductList: 0, 1:0.000", p.Name, p.Fineness);
// just two decimal places
String.Format("0:0.00", 123.4567); // "123.46"
String.Format("0:0.00", 123.4); // "123.40"
String.Format("0:0.00", 123.0); // "123.00"
// max. two decimal places
String.Format("0:0.##", 123.4567); // "123.46"
String.Format("0:0.##", 123.4); // "123.4"
String.Format("0:0.##", 123.0); // "123"
// at least two digits before decimal point
String.Format("0:00.0", 123.4567); // "123.5"
String.Format("0:00.0", 23.4567); // "23.5"
String.Format("0:00.0", 3.4567); // "03.5"
String.Format("0:00.0", -3.4567); // "-03.5"
//Zero formatting
String.Format("0:0.0", 0.0); // "0.0"
String.Format("0:0.#", 0.0); // "0"
String.Format("0:#.0", 0.0); // ".0"
String.Format("0:#.#", 0.0); // ""
【讨论】:
检查了这个,感谢链接真的很有用......但不幸的是不是我的解决方案。看起来好像小数点在存储到数据库时被截断了......值现在在控制台输出中显示为0.750
、0.670
和 0.470
以上是关于不需要的小数截断的主要内容,如果未能解决你的问题,请参考以下文章