从EF的使用中探讨业务模型能否脱离单一存储层完全抽象存在
上次赶时间,就很流水账地写了上次项目对EF的一次实践应用模式,因为太长了,也没能探讨太多,所以再继续扩展。
这次想探讨的是,实体,如果作为类似于领域模型的业务模型存在,它的数据能否来自不同的数据源。这个想法首先是来自于这次应用中,Model First + 代码补充的方式形成了一个极好的效果。一方面满足了范式,减少了数据存储量;另一方面利用了封装特性,向业务提供了一个符合业务期望的实体。
首先看一个例子
我用Model First建立了Account一个实体,实际生成的代码如下:
public partial class Account
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
对应地,上面三个字段分别对应着数据库中的三个字段。
然后,我再用Partial Class的方式,为Account进行扩充:
public partial class Account
{
public string FullName
{
get
{
if (this._fullName == null)
{
this._fullName = String.Format("{0} {1}", this.FirstName, this.LastName);
}
return this._fullName;
}
} string _fullName;
}
这里就是关键了。此时,业务逻辑拿到的称之为Account的就不再是简单的DAO对象了,而是一个有着四个业务所需字段的业务模型对象。有兴趣的可以去看看我上一篇《Entity Framework 与 面向对象》中间设计模式的部分,里面讲到了为实体应用上了继承、多态、封装等面向对象的设计方式以达到业务模型所需的效果。
我的问题
这种为Entity添加完整面向对象特性的方式,有着一种想法,那就是能否让一个Entity完全抽象架空于存储层,允许一个Entity的数据来自不同的数据源。
首先,如果在存储层的视角来看,示例中Account的三个字段Id、FirstName、LastName来自于关系数据库,而FullName来自于计算值,也就是内存。站在数据库的角度上来说,FullName确实是不符合范式,所以很“多余”。
如果从时间线来说,在实例化的时候,前三个数据库字段的数据就已经被加载了,而FullName是Lazy Load。
但是,对于业务来说,他获得的不过是一个包含四个字段的Account的实例。
那么我的问题就继续扩展了,一个业务模型,能不能将数据源完全封装,在业务获得该实体的时候,完全脱离关注实现?
当我获得一个产品,那么这个产品的基本属性来自关系数据库,产品介绍来自NoSql,统计值来自动态计算。重要的是,这要是一个对象,而不是自行用多个对象拼装出来的。
实际上,是封装的问题
实际上,来到这里,就已经很明朗,这是一个封装的问题。我们从前遇到的是关系数据库和面向对象的阻抗失配,然后用ORM解决了。而今天,我们还可能遇到非强类型对象和非关系数据库以及强类型对象和关系数据库混合使用的问题,而且这使得其成为常态。
通常,因为一个特性的原因,我们要在技术上进行选型。要么用静态语言,要么用动态语言。但是当出现一个用另一种方式更合适的时候,实现就变得很别扭了。
比如用上面产品的问题,多少人是把产品详情作为整个文本值存在一个字段里呢?多少人又在用一张表来解决动态字段的问题呢?
实现,现实吗
在Account的例子中,这种行为很容易实现。一方面依托于EF提供了相关的支持,另一方面是两个存储源具有时间上的关联。在进行一项业务的时候,所有数据库里,也就是存储在持久化存储器内的数据,最终都要读取到内存中才能被操作。这种纵向的关系,方面了应该来自于内存的数据源在产生数据的行为嵌入到整个业务过程中。
但是当两个数据源没有纵向关系而是平行关系的时候,问题就来了。这个状况就跟当年的阻抗失配的问题类似。
首先是一个迭代的问题。
大家都知道,获取数据是有获取成本的。数据在抽象层面是“获取”,在实现层面是一次“拷贝”,拷贝的过程包括了“传输”。拷贝和传输就是数据获取的成本,这个成本在一些情形可以被很大的放大,比如从前的递归查询。
如果不把递归写成SQL,那么在业务层面进行解决的话,就要往返很多次数据库获取数据。产生的业务结果是一样的,但产生的性能结果差异极大。
而我假象的获取数据的行为是这样的:
可以简单当两个数据源的时候,会存在一个“数据汇合”的问题,其实就是一个同步和匹配问题。
两个数据源获取到的数据需要匹配上,在一个大量查询的时候就变得很麻烦了。如果按照顺序进行匹配不就简单了?但是要知道,“顺序”是个很奇怪的命题,你查找到的数据是一个集合或者列表才有“顺序”,对于NoSQL一类Key-Value的形态,如何定义顺序呢?
另外,如果是要一个数据源强行配合另一个数据源,那么一次数据获取行为的效率,就是由最慢的一个数据源决定的。
我再是想一下,如果是全部或者部分延迟加载,那么是不是说,读取数据都需要是异步的,而且合并数据的情况下,需要有一个用以合并数据的线程。
我打算尝试
实际会遇到什么情况不好说,所以我倒是乐于去尝试一下。
一开始的思路,是先尝试继续用扩充字段,然后把数据源获取封装好;然后我应该尝试去切入LinQ Provider,看看能不能在LinQ中下手,这对于.NET的使用或许更重要。
从EF的使用中探讨业务模型能否脱离单一存储层完全抽象存在的更多相关文章
- EF Core中避免贫血模型的三种行之有效的方法(翻译)
Paul Hiles: 3 ways to avoid an anemic domain model in EF Core 1.引言 在使用ORM中(比如Entity Framework)贫血领域模型 ...
- 分析业务模型-类图(Class Diagram)
分析业务模型-类图(Class Diagram) 分析业务模型-类图(Class Diagram)(上) 摘要:类图(Class Diagram)可能是用得最多的一种UML图.类图的基本语法并 ...
- BIEE入门(三)业务模型层
正如它的名字所示(Business Model and Mapping Layer),业务逻辑层需要把物理层的数据源以一种业务用户的视角来重新组织物理层的各个数据源(所谓的Mapping),同时在业务 ...
- How to: Create a Business Model in the XPO Data Model Designer 如何:在 XPO 数据模型设计器中创建业务模型
This topic provides step-by-step instructions on how to use the XPO Data Model Designer in XAF appli ...
- 电商架构设计-通过系统和业务拆分,遵循单一职责原则SRP,保障整个系统的可用性和稳定性
个人观察 1.通过系统和业务拆分,遵循单一职责原则SRP,保障整个系统的可用性和稳定性. 2.单一职责原则SRP,真的很关键,广大程序员需要不断深入理解这个原则. 3.架构图是架构师的重要输出,通过图 ...
- JVM并发机制的探讨——内存模型、内存可见性和指令重排序
并发本来就是个有意思的问题,尤其是现在又流行这么一句话:“高帅富加机器,穷矮搓搞优化”. 从这句话可以看到,无论是高帅富还是穷矮搓都需要深入理解并发编程,高帅富加多了机器,需要协调多台机器或者多个CP ...
- 使用EF Model First创建edmx模型,数据库有数据的情况下,如何同时更新模型和数据库
使用"EF Model First",我们可以很直观地在edmx文件中创建数据模型,并根据模型生成数据库,整个过程快速而高效.可当数据库中有了一定的数据量,同时,可能需要对模型中字 ...
- ASP.NET Core 使用 SQLite 教程,EF SQLite教程,修改模型更新数据库,适合初学者看懂详细、简单教程
SQLIte 操作方便,简单小巧,这里笔者就不再过多介绍,感兴趣可以到以下博文 https://blog.csdn.net/qq_31930499/article/details/80420246 文 ...
- BW ON HANA 业务模型关系与数据取数
在接到业务需求之后,我认为重要的是理清楚自己该做什么.来实现业务.由于不了解业务,还是走了很多弯路.本可以不用这么做,还是这么做了.自然你最傻瓜的按照用户的方式去实现是没有问题的. 会使后面的人难以维 ...
随机推荐
- .Net多线程编程—并发集合
并发集合 1 为什么使用并发集合? 原因主要有以下几点: System.Collections和System.Collections.Generic名称空间中所提供的经典列表.集合和数组都不是线程安全 ...
- jQuery UI resizable使用注意事项、实时等比例拉伸及你不知道的技巧
这篇文章总结的是我在使用resizable插件的过程中,遇到的问题及变通应用的奇思妙想. 一.resizable使用注意事项 以下是我在jsfiddle上写的测试demo:http://jsfiddl ...
- KMP算法求解
// KMP.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using namespac ...
- C语言 · 整数平均值
编写函数,求包含n个元素的整数数组中元素的平均值.要求在函数内部使用指针操纵数组元素,其中n个整数从键盘输入,输出为其平均值. 样例输入: (输入格式说明:5为输入数据的个数,3 4 0 0 2 是以 ...
- OpenCASCADE Expression Interpreter by Flex & Bison
OpenCASCADE Expression Interpreter by Flex & Bison eryar@163.com Abstract. OpenCASCADE provide d ...
- 46张PPT讲述JVM体系结构、GC算法和调优
本PPT从JVM体系结构概述.GC算法.Hotspot内存管理.Hotspot垃圾回收器.调优和监控工具六大方面进行讲述.(内嵌iframe,建议使用电脑浏览) 好东西当然要分享,PPT已上传可供下载 ...
- jquery插件的用法之cookie 插件
一.使用cookie 插件 插件官方网站下载地址:http://plugins.jquery.com/cookie/ cookie 插件的用法比较简单,直接粘贴下面代码示例: //生成一个cookie ...
- 设计模式之结构类模式大PK
结构类模式大PK 结构类模式包括适配器模式.桥梁模式.组合模式.装饰模式.门面模式.享元模式和代理模式.之所以称其为结构类模式,是因 ...
- peer not authenticated的终极解决方案
一.前述 使用httpclient发起https请求时,可能会遇到如下异常: javax.net.ssl.SSLPeerUnverifiedException: peer not authentica ...
- 从源码浅析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler
熟悉WebForm开发的朋友一定都知道,Page类必须实现一个接口,就是IHttpHandler.HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET ...