ActiveRecord模式简介 ActiveRecord模式是Martin Fowler的企业应用架构模式中提到的一种数据访问模式如下图Person类包含lastName, firstName等这些属性一个Person类的实例对应数据库的一个Person表或视图的一条记录每一个属性对应数据库记录的一个字段同时Person类包含CRUD方法封装了对数据库的操作Person类同时还可以包含其他和这条记录相关的业务方法。ActiveRecord模式和Repository模式从外部接口上看起来在很多方面很像但理念其实有区别ActiveRecord和数据库访问紧耦合它更像是对数据库中的一条记录的包装类Repository则隔离了具体的数据访问和领域对象的CRUD的耦合这样一层隔离的存在使得Repository更灵活他可以还是像ActiveRecord一样包装一条数据库记录却不限于数据库数据也可以保存在任何地方只要外部接口不变其内部实现有更灵活性。ActiveRecord的属性一般应该完全对应于数据库的字段而Repository的属性则没有这样的限制。ActiveRecord对数据库访问的紧耦合也不完全是缺点紧耦合的好处是ActiveRecord上的方法的参数也可以是和数据库紧耦合的例如它的CRUD方法的参数可以包含数据库特定的信息如字段信息或者数据库特有的查询条件面向数据库的查询条件从数据库的视角当然更直观而Repository在外部接口上原则上是不能有任何数据库特定的信息的如果最终还是要查数据库还需要额外把非数据库特定的查询条件转换为数据库特定的查询条件对于参数复杂的查询处理查询条件的成本要高得多。什么是WCF可序列化的ActiveRecord这里的“WCF可序列化”指的是一个类可以被支持WCF DataContract序列化的类进行序列化。这里“WCF可序列化的ActiveRecord”指的是不仅仅ActiveRecord可序列化还包括服务于ActiveRecord的查询条件也可以被序列化。ActiveRecord及其查询条件可以被WCF序列化就意味着他们可以通过WCF服务进行远程通信换句话说他们可以作为DTO对象。在有关ActiveRecord的讨论中经常会被提到ActiveRecord不能用作DTO因为其内部包装着数据库访问尤其不能跨进程边界传递ActiveRecord实例。这种说法当然没错不过他有一个前提就是如果ActiveRecord实例连接着数据库通过ActiveRecord上的CRUD可以直接访问数据库的话。换句话说如果可以解除ActiveRecord实例对数据库的连接例如可以提供Attach(db)/Detach()方法将一个ActiveRecord实例绑定或解绑具体的数据库连接那么把它作为DTO我觉得未尝不可。让数据库查询条件作为DTO会不会有问题呢在传统的程序开发中一般我们说传递“数据库查询条件”往往指的是传递SQL片段虽然传递SQL使得查询条件非常灵活却毫无疑问是不安全的。但是如果是对SQL语义的查询条件进行强类型的包装则可以做到没有这样的安全隐患却又可以保留查询条件灵活的特性。如果从安全性的角度能够接受ActiveRecord及包含数据库查询语义的强类型的ActiveRecord的查询条件作为WCF服务的DTO进行传递那么我们就可以再来谈谈由此带来的好处了。以下假设我们可以用一个强类型的Criteria对象来表示一个任意的数据库语义的查询条件并且它可序列化可以作为DTO进行传递。简化CRUD和WCF服务接口。相对于Repository只能使用一个或多个非数据库语义的参数来描述查询条件如果我们可以用一个Criteria对象来表示一个任意的数据库语义的查询条件我们就只需要一个Find(Criteria criteria)方法作为所有的查询条件的入口。则无论对于CRUD本身的API还是WCF服务的API都得到了极大的简化而描述能力却大大提升。简化数据库查询语句的构造和执行。在数据层的数据库查询的执行端。由于我们的Criteria是基于数据库语义的强类型封装翻译成SQL的成本相对于Repository只能使用一个或多个非数据库语义的参数来描述的查询条件到SQL的翻译成本要低得多语义上也直接得多。需要注意的问题如何限制客户端的查询能力由于采用这样一种方案的ActiveRecord使得客户端拥有了最大化的自定义查询能力我们一定需要有一些机制可以限制这种能力在Find(Criteria criteria)的实现端在执行查询之前需要根据一定的规则验证criteria是否允许执行在客户端的查询对象上我们也可以有一些限制比如只允许某些字段作为查询条件或者有些ActiveRecord是只读的不允许写操作。以数据库的思维来构造查询条件。即使在允许的查询条件范围之内由于不同的查询组合条件潜在地会导致不同语义的数据库查询被执行不同的语义可能会导致不同的性能差异因此在客户端构造查询条件的时候更大程度上我们需要以数据库的思维来构造而不仅仅是以业务的思维。有人可能要问客户端代码需要以数据库的思维来写或者可能影响到数据层的执行效率这样的设计是合理的吗我觉得要看情况。首先ActiveRecord是允许和数据库紧耦合的从这个角度ActiveRecord的客户端本身就是允许通过ActiveRecord的外部接口接触到数据库特定语义的。从这个角度来说给予客户端一定的构造查询条件的自由度至少是说得过去的。