Ø  前言

本文主要解决 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 类型精度问题的更多相关文章

  1. 在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 ...

  2. Entity Framework 教程——Entity Framework中的实体类型

    Entity Framework中的实体类型 : 在之前的章节中我们介绍过从已有的数据库中创建EDM,它包含数据库中每个表所对应的实体.在EF 5.0/6.0中,存在POCO 实体和动态代理实体两种. ...

  3. 开发 ASP.NET vNext 续篇:云优化的概念、Entity Framework 7.0、简单吞吐量压力测试

    继续上一篇<开发 ASP.NET vNext 初步总结(使用Visual Studio 2014 CTP1)>之后, 关于云优化和版本控制: 我本想做一下MAC和LINUX的self-ho ...

  4. Entity Framework 5.0系列之Code First数据库迁移

    我们知道无论是"Database First"还是"Model First"当模型发生改变了都可以通过Visual Studio设计视图进行更新,那么对于Cod ...

  5. Entity Framework 5.0

    今天 VS2012  .net Framework 4.5   Entity Framework 5.0  三者共同发布了. ( EF5 Released ) 在介绍新特性之前,先与大家回顾一下EF版 ...

  6. 云优化的概念、Entity Framework 7.0、简单吞吐量压力测试

    云优化的概念.Entity Framework 7.0.简单吞吐量压力测试 继续上一篇<开发 ASP.NET vNext 初步总结(使用Visual Studio 2014 CTP1)>之 ...

  7. [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 ...

  8. 精进不休 .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 ...

  9. 浅析Entity Framework Core2.0的日志记录与动态查询条件

    前言 Entity Framework Core 2.0更新也已经有一段时间了,园子里也有不少的文章.. 本文主要是浅析一下Entity Framework Core2.0的日志记录与动态查询条件 去 ...

随机推荐

  1. [luogu3620][APIO/CTSC 2007]数据备份【贪心+堆+链表】

    题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏 ...

  2. Apache虚拟主机+AD压力测试

    <Directory "/usr/local/awstats/wwwroot"> Options NoneAllowOverride None Order allow, ...

  3. centos7修改默认网卡名称

    问题场景: 使用centos7有好一阵子了,安装过centos7的朋友都会发现网卡命名跟6.x系统的不一样,类似ifcfg-eno16780032, ens192,或者enp2s0等其他不习惯的.不容 ...

  4. LVS搭建负载均衡(二)DR模型

    应用场景:LVS配置负载均衡方式之一:dr 测试环境: 配置步骤: 1. 在主机lvs上安装ipvsadm ~]# yum install ipvsadm -y ~]# ipvsadm //启动:该命 ...

  5. RHEL7下用本地光盘或镜像iso文件做yum源

    应用场境:Redhat 系统想要直接在线通过yum的条件时需要注册,一般用户都是非注册的,这个时候如果要想通过yum安装新软件,我们可以通过将安装盘或者镜像iso文件设置为yum源的方式来进行. 测试 ...

  6. Typescript学习笔记(三)变量声明及作用域

    ts的变量声明有var,let和const,这尼玛完全跟es6一样嘛.就稍微介绍一下. 大多数js开发者对于var很熟悉了,原生js里没有块级作用域,只有函数作用域和全局作用域,还存在var的变量提升 ...

  7. Python基础之文件和目录操作

    1 .文件操作 1.1 文件打开和关闭 在python, 使用 open 函数, 可以打开一个已经存在的文件, 或者创建一个新文件. # 打开文件 f = open('test.txt', 'w') ...

  8. PHP快速排序算法

    说明: 通过设置一个初始中间值,来将需要排序的数组分成3部分,小于中间值的左边,中间值,大于中间值的右边,继续递归用相同的方式来排序左边和右边,最后合并数组 示例: <?php $a = arr ...

  9. 开源的电商 B2C、B2B2C 电商系统-关于shopnc版权问题处处是陷阱啊

    最近有好多人收到过shopnc的律师函,关于这可能大部分人都是在淘宝购买的,或者直接在33hao购买的.很多人可能没注意版权的问题,以为在33hao购买就没问题,但这只是陷阱,大家一定要注意 来源:h ...

  10. Luogu P4015 运输问题

    题目链接 \(Click\) \(Here\) 继续颓网络流\(hhhhh\),虽然这次写的是个大水题,但是早上水一个网络流果然还是让人心情舒畅啊- 最大费用最大流不用非得反着费用建边.只要没有正环, ...