ORM框架工作原理
ORM框架工作原理
所有的ORM框架的工作原理都离不开下面这张图,只是每个框架的实现程度不同但是最终的目的是相同的。
如果是一个ORM框架那么一定会有上图中蓝色部分的这几个元素,无论是增删改查对于ORM一定是以对象为起点,使用对象构造出LINQ表达式,这样我们在对象的世界中可以描述我们希望对数据库所进行的操作,LINQ的最终实现其实也是Lambda表达式(必尽LINQ在代码上会直观很多),功能较强的ORM中都会记录有对象类型到数据库对象的元数据,使用这些元数据可以将复杂的Lambda表达式翻译成一个通用的中间表达式,这个表达式其实是抽象于各个不同数据库的具体实现,最后中间表达式再按指定数据库的具体实现生成最终的SQL语句,交由ADO.NET对象执行到数据库,如果数据存在返回则会回写到CLR对象中。
ORM框架的优点
-
面向对象
-
基础的增删改查的sql语句会自动生成,无需手动书写
-
编译检测(数据库的表与Domain中的对象一致,否则会报错)
-
不会出现sql语句出错的情况
ORM框架的缺点
- Sql自动生成,不够灵活,只生成基础的增删改查是无法完全适用整个 系统,不确定是否使用索引
- 需要很多反射,不管是否有用都会反射出来,对时间空间有耗损
- 更新及删除数据一定要从数据库取回对象或附加对象才能操作
ORM框架开发的设计流程
以下流程是根据我所接触的项目中总结出来的,本次是通过EF框架的CodeFirst代码优先的方式实现的,数据库里的表对应对象服务Demain中的类,CodeFirst就是实现对象服务Demain与数据的映射。
流程图如下:
项目访问流程:
- UI界面层引用实体应用服务(Application)与对象服务(Domain)
- 通过抽象工厂从容器中(Container)获取实体应用服务对象:IDomainApp domainApp = Factory.Create<IDomainApp>();
- 实体应用服务通过T4模板生成实体应用接口(IDomainApp.cs)与实体应用接口的实现方法(DomainApp.cs)(T4模板生成方法下面有介绍)
- T4模板生成出来的方法存入容器,存入方法:Container.RegisterType<IDomainApp, DomainApp>();
- 实体仓储服务通过T4模板生成实体仓储接口(IDomainRepository.cs)与实体仓储接口的实现方法(DomainRepository.cs)(T4模板生成方法下面有介绍)
- T4模板生成出来的方法存入容器,存入方法:Container.RegisterType<IDomainRepository, DomainRepository>();
- 实体仓储服务的实体仓储的实体方法可以直接访问数据库,获取数据,获取出来的数据以实体对象或者实体对象列表的形式返回给UI界面层的调用方法
注释:当前UI界面是通过Linq的查询方式访问的实体应用服务,但是访问实体应用服务不只是局限于Linq查询方式
项目设计流程中服务的生成
数据库表的更新:
- 在Domian对象服务中生成对象类Domain.cs
- 在Repository实体仓储服务中执行T4模板(执行方法为重新保存 EntityCodeScript.tt文件),执行完成之后则会自动创建实体仓储操作接口与实体仓储操作接口的实现
- 在Application实体引用服务中更新T4模板(执行方法为重新保存 EntityCodeScript.tt文件),执行完成之后则会自动创建实体应用操作接口与实体应用操作接口的实现
- 打开程序包管理器控制台,默认项目选中Repository实体仓储服务
- 在控制台输入Add-Migration xxx,点击Enter键执行即可(xxx代码数据库更新的版本号)
- 在控制台输入update-database 直接更新数据库,或者输入 update-database -script查看更新数据库的sql代码
实体仓储服务的更新:
- 执行T4模板(执行方法为重新保存 EntityCodeScript.tt文件)生成实体仓储操作接口(IDomainRepository.cs)与实体仓储操作接口的实现方法(DomainRepository.cs)
- 确认新添加的对象服务类(Domain)是否存在类的映射关系,不存在则实体仓储服务更新完成
- 存在则在Mapping里添加新增的对象服务类(Domain)的实体类型(DomainMap.cs),在实体类型中配置映射关系
- 配置完成之后在EntityFrameUnitOfWork中添加实体类型,实现实体类型映射
实体应用服务的更新:
- 执行T4模板(执行方法为重新保存 EntityCodeScript.tt文件)生成实体应用操作接口(IDomainApp.cs)与实体应用操作接口的实现方法(DomainApp.cs)
- 把实体仓储服务中新生成的实体仓储操作接口与实体仓储操作接口的实现方法寄存在容器(Container)中,Container.RegisterType<IDomainRepository, DomainRepository>();
- 把实体应用服务中新生成的实体应用操作接口与实体应用操作接口的实现方法寄存在容器(Container)中,Container.RegisterType<IDomainApp, DomainApp>();
T4模板的设计:
根据对象类的主键标识的类型来创建对象类的访问接口与访问接口的实现
实体仓储服务的接口与接口实现如下:
1 IEnumerable<Type> modelTypes = assembly.GetTypes().Where(m => typeof(AggregateRoot<T>).IsAssignableFrom(m) && !m.IsAbstract);
2 foreach(Type modelType in modelTypes)
3 {
4 T4ModelInfo model = new T4ModelInfo(modelType, true);
5
6 //实体仓储操作接口
7 IEntityRepositoryTemplate irep= new IEntityRepositoryTemplate(model);
8 var path = string.Format(@"{0}\Auto", projectPath);
9 irep.Output.Encoding = Encoding.UTF8;
10 irep.RenderToFile(Path.Combine(path, irep.FileName));
11
12 //实体仓储操作实现
13 EntityRepositoryTemplate rep= new EntityRepositoryTemplate(model);
14 path = string.Format(@"{0}\Auto", projectPath);
15 rep.Output.Encoding = Encoding.UTF8;
16 rep.RenderToFile(Path.Combine(path, rep.FileName));
17
18 EntityFrameUnitOfWorkTemplate erep= new EntityFrameUnitOfWorkTemplate(model);
19 path = string.Format(@"{0}\Auto", projectPath);
20 erep.Output.Encoding = Encoding.UTF8;
21 erep.RenderToFile(Path.Combine(path, erep.FileName));
22 }
实体应用服务的接口与接口实现如下:
1 IEnumerable<Type> modelTypes = assembly.GetTypes().Where(m => typeof(AggregateRoot<T>).IsAssignableFrom(m) && !m.IsAbstract);
2 foreach(Type modelType in modelTypes)
3 {
4 T4ModelInfo model = new T4ModelInfo(modelType, true);
5
6 //实体应用操作接口
7 IEntityAppTemplate irep= new IEntityAppTemplate(model);
8 var path = string.Format(@"{0}\Auto", projectPath);
9 irep.Output.Encoding = Encoding.UTF8;
10 irep.RenderToFile(Path.Combine(path, irep.FileName));
11
12 //实体应用操作实现
13 EntityAppTemplate rep= new EntityAppTemplate(model);
14 path = string.Format(@"{0}\Auto", projectPath);
15 rep.Output.Encoding = Encoding.UTF8;
16 rep.RenderToFile(Path.Combine(path, rep.FileName));
17 }
总结:
本文是根据我参与过得项目中总结出来的,也是为了检验我对这个项目的理解来做个评判,只是以我自己的理解加看法来解析这个项目以及项目框架的搭建,留作以后作为参考价值使用
以上是我的个人见解,仅供参考。
参考自: