Entity Framework ORM框架经验总结

1、实体框架主键的类型约束问题

在我们搭建整个实体框架的过程中,我们一般都是抽象封装处理很多基础的增删改查、分页等常见的数据处理功能,如下所示。

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

上面的外键统一定义为object类型,因为我们为了主键类型通用的考虑。

在实际上表的外键类型可能是很多种的,如可能是常见的字符类型,也可能是int类型,也可能是long类型等等。如果我们更新、查找、删除整形类型的记录的时候,那么可能机会出现错误:

The argument types 'Edm.Int32' and 'Edm.String' are incompatible for this operation.

这些错误就是主键类型不匹配导致的,我们操作这些接口的时候,一定要传入对应类型给它们,才能正常的处理。

本来想尝试在内部进行转换处理为正确的类型的,不过没有找到很好的解决方案来识别和处理,因此最好的解决方法,就是我们调用这些有object类型主键的接口时,传入正确的类型即可。

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结
又或者是下面的代码:

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

2、递归函数的处理

在很多时候,我们都会用到递归函数的处理,这样能够使得我们把整个列表的内容都合理的提取出来,是我们开发常见的知识点之一。

不过一般在处理LINQ的时候,它的递归函数的处理和我们普通的做法有一些差异。

例如我们如果要获取一个树形机构列表,如果我们指定了一个开始的机构节点ID,我们需要递归获取下面的所有层次的集合的时候,常规的做法如下所示。

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

这里面的大概思路就是把符合条件的集合全部弄到DataTable集合里面,然后再在里面进行检索,也就是递归获取里面的内容。

上面是常规的做法,可以看出代码量还是太多了,如果使用LINQ,就不需要这样了,而且也不能这样处理。

使用实体框架后,主要就是利用LINQ进行一些集合的操作,这些LINQ的操作虽然有点难度,不过学习清楚了,处理起来也是比较方便的。

在数据访问层,处理上面同等的功能,LINQ操作代码如下所示。

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

基本上,可以看到就是两行代码了,是不是很神奇,它们实现的功能完全一致。

不过,也不是所有的LINQ递归函数都可以做的非常简化,有些递归函数,我们还是需要使用常规的思路进行处理。

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

不过相对来说,LINQ已经给我们带来的非常大的便利了。

 

3、日期字段类型转换的错误处理

我们在做一些表的时候,一般情况下都会有日期类型存在,如我们的生日,创建、编辑日期等,一般我们数据库可能用的是datetime类型,如果这个日期的类型内容在下面这个区间的话:

"0001-01-01 到 9999-12-31"(公元元年 1 月 1 日到公元 9999 年 12 月 31 日)

我们可能就会得到下面的错误:

从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值

一般之所以会报错数据类型转换产生一个超出范围的值,都是因为数据的大小和范围超出要转换的目标的原因。我们先看datetime2和datetime这两个数据类型的具体区别在哪里。

官方MSDN对于datetime2的说明:定义结合了 24 小时制时间的日期。 可将 datetime2 视作现有 datetime 类型的扩展,其数据范围更大,默认的小数精度更高,并具有可选的用户定义的精度。

这里值的注意的是datetime2的日期范围是”0001-01-01 到 9999-12-31″(公元元年 1 月 1 日到公元 9999 年 12 月 31 日)。而datetime的日期范围是:”1753 年 1 月 1 日到 9999 年 12 月 31 日“。这里的日期范围就是造成“从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值”这个错误的原因!!!

在c#中,如果实体类的属性没有赋值,一般都会取默认值,比如int类型的默认值为0,string类型默认值为null, 那DateTime的默认值呢?由于DateTime的默认值为”0001-01-01″,所以entity framework在进行数据库操作的时候,在传入数据的时会自动将原本是datetime类型的数据字段转换为datetime2类型(因为0001-01-01这个时间超出了数据库中datetime的最小日期范围),然后在进行数据库操作。问题来了,虽然EF已经把要保存的数据自动转为了datetime2类型,但是数据库中表的字段还是datetime类型!所以将datetime2类型的数据添加到数据库中datetime类型的字段里去,就会报错并提示转换超出范围。

解决方法如下所示:

这个问题的解决方法:

  1. C#代码中 DateTime类型的字段在作为参数传入到数据库前记得赋值,并且的日期要大于1753年1月1日。
  2. C#代码中 将原本是DateTime类型的字段修改为DateTime?类型,由于可空类型的默认值都是为null,所以传入数据库就可以不用赋值,数据库中的datetime类型也是支持null值的。
  3. 修改数据库中表的字段类型,将datetime类型修改为datetime2类型

例如,我在实体框架里面,对用户表的日期类型字段进行初始化,这样就能保证我存储数据的时候,默认值是不会有问题的。

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结
有时候,虽然这样设置了,但是在界面可能给这个日期字段设置了不合理的值,也可能产生问题。那么我们对于这种情况,判断一下,如果小于某个值,我们给它一个默认值。

有时候,虽然这样设置了,但是在界面可能给这个日期字段设置了不合理的值,也可能产生问题。那么我们对于这种情况,判断一下,如果小于某个值,我们给它一个默认值。

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

 

4、实体框架的界面处理

在界面调整这块,我们还是尽可能保持着的Enterprise Library的Winform界面样式,也就是混合型或者普通Winform的界面效果。不过这里我们是以混合式框架进行整合测试,因此实体框架的各个方面的调用处理基本上保持一致。

不过由于实体框架里面,实体类避免耦合的原因,我们引入了DTO的概念,并使用了AutoMapper组件进行了Entity与DTO的相互映射,具体介绍可以参考《Entity Framework 实体框架的形成之旅–数据传输模型DTO和实体模型Entity的分离与联合

》。

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

因此我们在界面操作的都是DTO对象类型了,我们在定义的时候,为了避免更多的改动,依旧使用***Info这样的类名称作为DTO对象的名称,***代表表名对象。

在混合式框架的界面表现层,它们的数据对象的处理基本上保持和原来的代码差不多。

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

但我们需要在WCF服务层说明他们之间的映射关系,方便进行内部的转换处理。

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

在实体框架界面层的查询中,我们也不在使用部分SQL的条件做法了,采用更加安全的基于DTO的LINQ表达式进行封装,最后传递给后台的也就是一个LINQ对象(非传统方式的实体LINQ,那样在分布式处理中会出错)。

如查询条件的封装处理如下所示:

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

而分页查询的处理,依旧和原来的风格差不多,只不过这里的Where条件为ExpressionNode 对象了,如代码所示、

            ExpressionNode where = GetConditionSql();             PagerInfo PagerInfo = this.winGridViewPager1.PagerInfo;            IList<UserInfo> list = CallerFactory<IUserService>.Instance.FindWithPager(where, ref PagerInfo);            this.winGridViewPager1.DataSource = new WHC.Pager.WinControl.SortableBindingList<UserInfo>(list);            this.winGridViewPager1.PrintTitle = "系统用户信息报表";

最后我们来看看整个实体框架的结构和界面的效果介绍。

界面效果如下所示:

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

代码结构如下所示:

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

架构设计的效果图如下所示:

Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

未经允许不得转载:996ICU » Entity Framework ORM框架经验总结

赞 (0) 打赏