上次赶时间,就很流水账地写了上次项目对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的使用中探讨业务模型能否脱离单一存储层完全抽象存在的更多相关文章

  1. EF Core中避免贫血模型的三种行之有效的方法(翻译)

    Paul Hiles: 3 ways to avoid an anemic domain model in EF Core 1.引言 在使用ORM中(比如Entity Framework)贫血领域模型 ...

  2. 分析业务模型-类图(Class Diagram)

    分析业务模型-类图(Class Diagram)     分析业务模型-类图(Class Diagram)(上) 摘要:类图(Class Diagram)可能是用得最多的一种UML图.类图的基本语法并 ...

  3. BIEE入门(三)业务模型层

    正如它的名字所示(Business Model and Mapping Layer),业务逻辑层需要把物理层的数据源以一种业务用户的视角来重新组织物理层的各个数据源(所谓的Mapping),同时在业务 ...

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

  5. 电商架构设计-通过系统和业务拆分,遵循单一职责原则SRP,保障整个系统的可用性和稳定性

    个人观察 1.通过系统和业务拆分,遵循单一职责原则SRP,保障整个系统的可用性和稳定性. 2.单一职责原则SRP,真的很关键,广大程序员需要不断深入理解这个原则. 3.架构图是架构师的重要输出,通过图 ...

  6. JVM并发机制的探讨——内存模型、内存可见性和指令重排序

    并发本来就是个有意思的问题,尤其是现在又流行这么一句话:“高帅富加机器,穷矮搓搞优化”. 从这句话可以看到,无论是高帅富还是穷矮搓都需要深入理解并发编程,高帅富加多了机器,需要协调多台机器或者多个CP ...

  7. 使用EF Model First创建edmx模型,数据库有数据的情况下,如何同时更新模型和数据库

    使用"EF Model First",我们可以很直观地在edmx文件中创建数据模型,并根据模型生成数据库,整个过程快速而高效.可当数据库中有了一定的数据量,同时,可能需要对模型中字 ...

  8. ASP.NET Core 使用 SQLite 教程,EF SQLite教程,修改模型更新数据库,适合初学者看懂详细、简单教程

    SQLIte 操作方便,简单小巧,这里笔者就不再过多介绍,感兴趣可以到以下博文 https://blog.csdn.net/qq_31930499/article/details/80420246 文 ...

  9. BW ON HANA 业务模型关系与数据取数

    在接到业务需求之后,我认为重要的是理清楚自己该做什么.来实现业务.由于不了解业务,还是走了很多弯路.本可以不用这么做,还是这么做了.自然你最傻瓜的按照用户的方式去实现是没有问题的. 会使后面的人难以维 ...

随机推荐

  1. 如何优雅的使用RabbitMQ

    RabbitMQ无疑是目前最流行的消息队列之一,对各种语言环境的支持也很丰富,作为一个.NET developer有必要学习和了解这一工具.消息队列的使用场景大概有3种: 1.系统集成,分布式系统的设 ...

  2. Convert BSpline Curve to Arc Spline in OpenCASCADE

    Convert BSpline Curve to Arc Spline in OpenCASCADE eryar@163.com Abstract. The paper based on OpenCA ...

  3. Android raw to bmp

    Android raw 格式转 bmp 图像 raw 保存的为裸数据,转换时都需要把它转成RGBA 的方式来显示.其中: 8位RAW: 四位RGBA 来表示一位灰度; 24位RAW: 三位RGB相同, ...

  4. 预览github里面的网页或dome

    1.问题所在: 之前把项目提交到github都可以在路径前面加上http://htmlpreview.github.io/?来预览demo,最近发现这种方式预览的时候加载不出来css,js(原因不详) ...

  5. 多线程爬坑之路-Thread和Runable源码解析

    多线程:(百度百科借一波定义) 多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提 ...

  6. 深入理解 JavaScript,以及 Linux 下的开发调试工具

    前言 JavaScript 是我接触到的第二门编程语言,第一门是 C 语言.然后才是 C++.Java 还有其它一些什么.所以我对 JavaScript 是非常有感情的,毕竟使用它有十多年了.早就想写 ...

  7. 说一说python的牛比与不爽

    本人写了10年php了.今年开始改写python了.不是说php有什么不好,php在自己的势力范围内还是很牛比的.只是我已经不能满足于php那两亩地了. 习惯了脚本,所以很自然就过度到python了. ...

  8. BPM生产安全管理解决方案分享

    一.方案概述生产安全管理是企业生产管理的重要组成部分,组织实施好企业安全管理规划.指导.检查和决策,保证生产处于最佳安全状态是安全管理的重要内容和职责.H3 BPM企业生产安全管理解决方案是一套专门为 ...

  9. 使用git进行源代码管理

    git是一款非常流行的分布式版本控制系统,使用Local Repository追踪代码的修改,通过Push和Pull操作,将代码changes提交到Remote Repository,或从Remote ...

  10. exp/imp 与 expdp/impdp 区别

    在平常备库和数据库迁移的时候,当遇到大的数据库的时候在用exp的时候往往是需要好几个小时,耗费大量时间.oracle10g以后可以用expdp来导出数据库花费的时间要远小于exp花费的时间,而且文件也 ...