虽然从技术角度讲,DataTable与EntityObject并没有什么可比性,然而,它暗示了一场革命正在悄然进行着,即使是微软,也摆脱不了这场革命的飓风。
软件设计思想需要革命,需要摆脱原有的思路,而走向面向领域的道路。你或许会觉得听起来很玄乎,然而目前软件开发的现状使你不得不接受这样的现实,仍然有大帮的从业人员成天扯着数据库不放,仍然有大帮的人在问:“我要实现xxxx功能,我的数据库应该如何设计?”这些人犯了根本性的错误,就是把软件的目的搞错了,软件研究的是什么?是研究如何使用计算机来解决实际(领域)问题,而不是去研究数据应该如何保存更合理。这方面的事情我在我以前的博文中已经说过很多次了,在此就不再重复了。
当然,很多读者会跟我有着相同的观点,也会觉得我很“火星”,但这都不要紧,上面我所说的都是一个引子,希望能够帮助更多“步入歧途”的从业人员 “走上正路”。不错,软件设计应该从“数据库驱动”走向“领域驱动”,而领域驱动设计的实践经验正是为设计和开发大型复杂的软件系统提供了实践指导。
回到我们的副标题,从DataTable到EntityObject,你看到了什么?看到的是微软在领域驱动上的进步,从DataTable这一纯粹的数据组织形式,到EntityObject这一实体对象,微软带给我们的不仅仅是技术框架,更是一套面向领域的解决方案。
.NET 4.0来了,随之而来的是实体框架(EntityFramework,简称“EF”),在本系列文章中,我将结合领域驱动设计的实践知识,来剖析EF的具体应用过程,当然,现在的EF还并不是那么完善,我也非常期待能够看到,今后微软能够继续发展和完善EF,使其成为微软领域驱动工具箱中的重要角色。
先不说EF,首先我们简要地分析一下,作为一种框架,要支持领域驱动的思想,需要满足哪些硬性需求,之后再仔细想想,.NET EF是否真的能够很好地应用在领域驱动上。
首先需要能够正确对待“领域模型”的概念。领域模型与数据模型不同,它表述的是领域中各个类及其之间的关系。类关系是多样的,比如组合、聚合、继承、实现、约束等,而数据模型不是一对多,就是多对多。从领域驱动设计的角度看,数据库只不过是存储实体的一个外部机制,是属于技术层面的东西。数据模型主要用于描述领域模型对象的持久化方式,应该是先有领域模型,才有数据模型,领域模型需要通过某种映射而产生相应的数据模型。因此,框架必须支持从领域模型到数据模型的映射。
EF不仅支持从领域模型生成数据库的DDL,而且支持从数据库结构来生成“领域模型”。我倒是觉得后者可以去掉,因为从数据库得到的已经不是领域模型了。你会问为什么,我可以告诉你,单纯的数据是没办法描述领域概念的。比如:你的数据库里有一个表叫做“Customer”,在通过数据库结构生成“领域模型”的时候,Visual Studio当然会帮你生成一个“领域对象”叫做Customer,但如果我把这数据表的名字改为“abc”,虽然里面还是存的客户信息,但EF并不知道这一点,也是照样生成一个“abc”的类,而这样的东西能算是领域对象吗?因此,数据依赖于实体,是实体的状态,离开实体的数据毫无意义
上图中标记的内容,根据领域驱动设计的思想,是不应该保存的。然而.NET是一个产品,它需要顾及到各种需求,因此,“从数据库生成模型”的功能也将被保留下来
对“聚合”概念的支持。聚合是一系列表述同一概念的相互关联的实体的集合,比如销售订单、销售订单行以及商品,这三个实体可以整合成一个聚合,销售订单则是聚合的根。关于聚合的问题将在后续文章中讨论。为什么引入聚合?这是领域驱动设计处理大型软件系统的一种独到的方式。软件系统的实体对象可能非常多,之间的关系也可能错综复杂,那么,当我们需要从外部持久化机制“唤醒”(或者说读取)某个实体对象的时候,是不是需要将它以及它所关联的所有对象都一并读入内存呢?当然不是,因为我们只需要关注整个问题的某个方面。比如在读取客户数据的时候,我们或许会将这个客户的所有订单显示出来,但不会将每个订单的订单行也全部读出来,因为现在我们还没有决定是否真的需要查看所有的订单行。