解决 Entity Framework 6.0 decimal 类型精度问题
Ø 前言
本文主要解决 EF 中对于 MSSQL 数据库的 decimal 类型经度问题,经实验该问题仅在 CodeFirst 模式的情况下发生,话不多说直接看代码。
1. 假设我们有一张 Customer 数据表,主要探究:Longitude、Latitude、LonLatSum 这三个字段。
1) 结构如下:
CREATE 的数据)
1) C# 代码如下:
using (MyTestingEntities context = new MyTestingEntities())
{
Customer entity = context.Customers.Attach(new Customer() { Id = 1 });
entity.Longitude = 123.1256789f; //123.125679
entity.Latitude = 456.1295678d; //456.1295678
entity.LonLatSum = (decimal)(entity.Longitude + entity.Latitude); //579.255246816113M
context.Configuration.ValidateOnSaveEnabled = false;
result = context.SaveChanges() > 0;
}
2) 生成SQL:
exec 位小数。
2. Latitude:float 类型(对应 C# 中的 double 类型),保留了7位小数。
3. LonLatSum:decimal 类型(对应 C# 中的 decimal 类型),也保留了7位小数。
4. OK 这是正常的。
3. 然后,我们再使用 Code Frirst 的方式对数据更新(更新 Id 为2的数据)
1) C# 代码如下:
using (MyTestingContext context = new MyTestingContext())
{
Customer entity = context.Customer.Attach(new Customer() { Id = 2 });
entity.Longitude = 123.1256789f; //123.125679
entity.Latitude = 456.1295678d; //456.1295678
entity.LonLatSum = (decimal)(entity.Longitude + entity.Latitude); //579.255246816113M
result = context.SaveChanges() > 0;
}
return result;
2) 生成SQL:
exec )和小数位数(2位)的方式生成了,结果 SQL 的类型声明是这样:decimal(18,2)。
3) 搞清楚了问题,下面我们就来解决这个问题吧。
5. 解决问题
1) 创建一个 DecimalPrecisionAttribute 特性类
/// <summary>
/// 用于指定 decimal 类型的精确度与小数保留位数。
/// </summary>
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public class DecimalPrecisionAttribute : Attribute
{
private byte _precision;
/// <summary>
/// 精确度。
/// </summary>
public byte Precision
{
get { return _precision; }
set { _precision = value; }
}
private byte _scale;
/// <summary>
/// 小数保留位数。
/// </summary>
public byte Scale
{
get { return _scale; }
set { _scale = value; }
}
/// <summary>
/// 根据指定的精确度与小数保留位数,初始化 DecimalPrecisionAttribute 的实例。
/// </summary>
/// <param name="precision">精确度。</param>
/// <param name="scale">小数保留位数。</param>
public DecimalPrecisionAttribute(byte precision, byte scale)
{
this.Precision = precision;
this.Scale = scale;
}
}
2) 再创建一个 DecimalPrecisionAttributeConvention 类(表示 DecimalPrecisionAttribute 的一种约定)
1. 该类继承于 System.Data.Entity.ModelConfiguration.Conventions.PrimitivePropertyAttributeConfigurationConvention 类。
2. 并实现 Apply 抽象方法,通俗点说:该方法在“生成 SQL”时被调用,对于打了 DecimalPrecisionAttribute 标记的实体属性,精度将根据 configuration.HasPrecision() 方法中的设置去生成。
/// <summary>
/// 表示 DecimalPrecisionAttribute 的一种约定。
/// </summary>
public class DecimalPrecisionAttributeConvention
: PrimitivePropertyAttributeConfigurationConvention<DecimalPrecisionAttribute>
{
public override void Apply(ConventionPrimitivePropertyConfiguration configuration, DecimalPrecisionAttribute attribute)
{
if (attribute.Precision < 1 || attribute.Precision > 38)
{
throw new InvalidOperationException("Precision must be between 1 and 38.");
}
if (attribute.Scale > attribute.Precision)
{
throw new InvalidOperationException("Scale must be between 0 and the Precision value.");
}
configuration.HasPrecision(attribute.Precision, attribute.Scale);
}
}
3) 在数据上下文的 OnModelCreating() 方法将该 DecimalPrecisionAttributeConvention(约定)加入数据约定集合中。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Add(new DecimalPrecisionAttributeConvention());
}
4) 最后一步,将需要设置小数位数的属性打上 DecimalPrecision 标记,例如:
[DecimalPrecision(18, 7)]
public decimal LonLatSum { get; set; }
5) 好了之后再次运行代码,生成 SQL 如下:
exec sp_executesql N'UPDATE [dbo].[Customer]
SET [Longitude] = @0, [Latitude] = @1, [LonLatSum] = @2
WHERE ([Id] = @3)
',N'@0 real,@1 float,@2 decimal(18,7),@3 int',@0=123.12567901611328,@1=456.12956780000002,@2=579.2552468,@3=2
6) 结果如下:
7) OK,这样就与 DB First 生成的 SQL 没什么区别了。
解决 Entity Framework 6.0 decimal 类型精度问题的更多相关文章
- 在Entity Framework 4.0中使用 Repository 和 Unit of Work 模式
[原文地址]Using Repository and Unit of Work patterns with Entity Framework 4.0 [原文发表日期] 16 June 09 04:08 ...
- Entity Framework 教程——Entity Framework中的实体类型
Entity Framework中的实体类型 : 在之前的章节中我们介绍过从已有的数据库中创建EDM,它包含数据库中每个表所对应的实体.在EF 5.0/6.0中,存在POCO 实体和动态代理实体两种. ...
- 开发 ASP.NET vNext 续篇:云优化的概念、Entity Framework 7.0、简单吞吐量压力测试
继续上一篇<开发 ASP.NET vNext 初步总结(使用Visual Studio 2014 CTP1)>之后, 关于云优化和版本控制: 我本想做一下MAC和LINUX的self-ho ...
- Entity Framework 5.0系列之Code First数据库迁移
我们知道无论是"Database First"还是"Model First"当模型发生改变了都可以通过Visual Studio设计视图进行更新,那么对于Cod ...
- Entity Framework 5.0
今天 VS2012 .net Framework 4.5 Entity Framework 5.0 三者共同发布了. ( EF5 Released ) 在介绍新特性之前,先与大家回顾一下EF版 ...
- 云优化的概念、Entity Framework 7.0、简单吞吐量压力测试
云优化的概念.Entity Framework 7.0.简单吞吐量压力测试 继续上一篇<开发 ASP.NET vNext 初步总结(使用Visual Studio 2014 CTP1)>之 ...
- [EF2]Sneak Preview: Persistence Ignorance and POCO in Entity Framework 4.0
http://blogs.msdn.com/b/adonet/archive/2009/05/11/sneak-preview-persistence-ignorance-and-poco-in-en ...
- 精进不休 .NET 4.5 (12) - ADO.NET Entity Framework 6.0 新特性, WCF Data Services 5.6 新特性
[索引页][源码下载] 精进不休 .NET 4.5 (12) - ADO.NET Entity Framework 6.0 新特性, WCF Data Services 5.6 新特性 作者:weba ...
- 浅析Entity Framework Core2.0的日志记录与动态查询条件
前言 Entity Framework Core 2.0更新也已经有一段时间了,园子里也有不少的文章.. 本文主要是浅析一下Entity Framework Core2.0的日志记录与动态查询条件 去 ...
随机推荐
- 通俗讲解MOSFET
一位工程师曾经对我讲,他从来不看MOSFET数据表的第一页,因为“实用”的信息只在第二页以后才出现.事实上,MOSFET数据表上的每一页都包含有对设计者非常有价值的信息.但人们不是总能搞得清楚该如何解 ...
- nodejs的某些api~(六)HTTPS
node的HTTPS模块接口与HTTP其实差不多,就是多了一个认证证书,私钥的配置等等,API都相似的. 在客户端服务器通信的方法中,只有HTTPS是最安全的,它的原理是客户端和服务器发送自己的公钥, ...
- P1966 火柴排队
这道题需要小小的思考一波 (然而我思考了两节课) 好,我们先得出一个结论:a中第k大的与b中第k大的一定要排在一起,才能保证最小. 然后发现:挪a,b其实没有区别,故我们固定a,挪b. 然后我们就思考 ...
- 任意模数NTT
任意模数\(NTT\) 众所周知,为了满足单位根的性质,\(NTT\)需要质数模数,而且需要能写成\(a2^{k} + r\)且\(2^k \ge n\) 比较常用的有\(998244353,1004 ...
- [luogu4626][一道水题2]
题目链接 思路 这个首先想到质因数分解.然后发现只要对于每个质数将ans乘以这个质数在从1到n中出现过的最高指数次就行了. 这个\(10^8\)令人发指.一直tle,最后发现吸口氧才能过.. 代码 # ...
- MVC之 自定义过滤器(ActionFilterAttribute)
一.自定义Filter 自定义Filter需要继承ActionFilterAttribute抽象类,重写其中需要的方法,来看下ActionFilterAttribute类的方法签名. //表示所有操作 ...
- operation=
x+=xxx 先执行xxx,再x=x+xxx 一个与之的问题 C(n,n/2) for (i=n;i>n/2;i--) v*=i/(n+1-i);每次先执行i/(n+1-i),然后 ...
- python之迭代器、生成器与面向过程编程
目录 一 迭代器 二 生成器 三 面向过程编程 一.迭代器 1.迭代器的概念理解 ''' 迭代器从字面上理解就是迭代的工具.而迭代是每次的开始都是基于上一次的结果,不是周而复始的,而是不断发展的. ' ...
- 推荐几个Mac插件帮你提升工作效率
下面这篇文章是小编看到的很好的文章,分享给大家,小编前几天也整理了很多mac专题文章.更多专题,可关注[磨人的小妖精],查看我的文章,也可上[风云社区 SCOEE],查找和下载相关软件资源. (一)综 ...
- Java运算符和引用数据类型(Scanner、Random)
运算符 算术运算符: 运算符 运算规则 范例 结果 + 正号 +3 3 + 加 2+3 5 + 连接字符串 “中”+“国” “中国” - 负号 int a=3;-a -3 - 减 3-1 2 * 乘 ...