最原始的 ORM 需求就是将关系数据库查询出来的结果数据转换成强类型对象使用,解决查询结果数据在面向对象语言中使用不够方便的问题。
接下来的需求就是使用面向对象的方式查询数据库(也就是抛弃 SQL 语句这种不方便维护的字符串),这个阶段的 ORM 框架可谓五花八门, 为了能够在面向对象语言中模拟 SQL 语句费尽心思。
我曾经也在这些方面折腾过一段时间,可是慢慢的发现这种做法不仅带来了各种限制,而且相比于直接写 SQL 语句并不能提高多少开发效率,该写的都少不了,唯一的优势就是有 IDE 的智能提示不那么容易出错。
面向对象的本质是抽象,而不是折腾各种写法;而关系模型并不具备面向对象特性,强行将两者融合为一体并不能得到超体,而是各种别扭。我觉得单纯从写法的角度考虑,像 LINQ 这种直接被 IDE 与编译器内置支持的才是正道。
有时候放弃也是一种不错的选择,比如在这个问题里面我就放弃了关系模型,选择了面向对象,这个决定让我从 ORM 问题中解脱出来。
放弃了关系模型,也就放弃了关系数据库特有的功能特性,数据库也就退化成了支持索引查询的储存设备,数据处理的重心由数据库转到了程序逻辑中。

一般来说缓存是为了提高数据查询效率而保存的查询结果,避免重复的计算操作。
很多人的脑海里,一提到缓存就是 Key-Value。可能是由于主流的缓存框架用的都是这种模型,因为对于分布式缓存结构而言,K-V 模式是简单高效率而且容易实现的。
但是我要说的缓存,既不是保存查询结果,也不是分布式 K-V 模型。
我要说的缓存是针对查询需求,在本地内存中使用合适的数据结构组织与查询条件有关的数据源,尽可能的降低查询需求以及相关操作的时间复杂度,当然要做到这一点需要一定的数据结构与算法知识。
缓存数据源对于内存的使用量与性能效果基本都是可控的,而查询结果的体量则是不可控的,实时性也是难以保障的,当然对于某些计算量大而且体量不可控的查询结果还是需要 K-V 分布式缓存处理的。
缓存数据源相当于内存索引,查询都在内存中处理,可以减少数据库物理层的索引需求,数据库物理层基本只需要主键索引。
缓存数据源可以方便的实时更新计算数据,对于计算列不存在事务问题,减少数据库表格中的计算列这种冗余需求,同时减少数据更新操作。
缓存数据源可以很方便的在程序逻辑中访问数据,带来类似于 LINQ to Object 的编码体验,可以快速应对数据查询需求的变化,不再为复杂的查询需求而烦恼。
当然缓存数据源可能需要使用大量内存,我认为大内存比人工优化代价更低。

抛弃了关系模型的 ORM 只存在单表格操作,可以真正的抛弃 SQL 及其相关理念。
因为应用层没有 SQL 语句,所以不存在不可控的数据更新,从而做到简单可控的数据同步,可以与数据源缓存自然的融合到一起,进而可以为实现统一规划全局数据定义整体开发框架提供基础支持。
由于 ORM 内存索引缓存框架 的实现依赖 LambdaExpression,所以暂时不支持 .NET Framework 2.0
该功能需要引用 AutoCSer\Packet\*\AutoCSer.Sql.dll,需要在工程项目中配置静态代码生成

该框架将 ORM 分成表格数据模型数据表格两层,表格数据模型主要用于定义映射到物理存储的表格数据列数据表格主要用于定义表格名称与数据库连接信息。

1. 为表格数据模型创建一个类库项目,根据需求添加表格数据模型 class,这个类型必须是非密封的 public partial,因为静态代码生成需要生成一个继承自该类型的表格模型中间层用于生成各种基础相关配置的中间层代码。

2. 给表格数据模型添加以字段表示的数据列,并根据需求为这些字段添加 [AutoCSer.Sql.Member] 以配置数据列信息。
为了在全局角度规范数据定义,AutoCSer 需要合理规划字段与属性的作用。在默认规则中,字段用于表示原始数据,属性则用于表示原始数据经过某种计算以后的结果,所以数据列只支持字段而不支持属性。

3. 给表格数据模型 class 添加表格模型申明配置 [AutoCSer.Sql.Model] 通知静态代码生成为该类型生成表格模型中间层代码。

4. 给该项目配置静态代码生成并编译项目,然后将生成的表格模型中间层代码源文件 {项目名称}.AutoCSer.cs 添加到项目中。
表格模型中间层是一个名为 SqlModel 继承自表格数据模型的泛型类型,第一个泛型参数类型 tableType 用于申明数据表格类型,多个数据表格可以继承自同一个表格模型中间层
如果申明了 [AutoCSer.Sql.Model(IsMemberCache = true)] 则会有第二个泛型参数类型 memberCacheType 用于申明缓存扩展类型,正常情况下会同时指定整表缓存类型 CacheType

表格数据模型 参考示例 AutoCSer\Example\OrmModel\MemberCache.cs
数据表格 参考示例 AutoCSer\Example\OrmTable\MemberCache.cs

5. 为数据表格创建一个项目并引用表格数据模型类库项目,在这个项目中添加继承自表格模型中间层数据表格 class,在 AutoCSer 的规划中这个项目是默认的数据访问业务逻辑服务层。

6. 给数据表格 class 添加表格模型申明配置 [AutoCSer.Sql.Table],必须指定 ConnectionName 用于配置数据库连接配置名称,该名称必须匹配代码配置中的配置名称。

代码配置 参考示例 AutoCSer\Example\OrmTable\Config.cs

7. 在数据表格继承的表格模型中间层中有一个名称为 sqlTable 的静态字段,它继承自 AutoCSer.Sql.Table<tableType, modelType>,提供数据表格的操作 API。
sqlTable 初始化的时候会根据表格数据模型数据表格信息自动创建数据库表格,对于已经存在的表格缺少数据列的情况会自动补全。
由于数据安全问题,初始化过程不会对已经存在的数据列进行修改操作,请在程序运行前自行维护数据库表格。
由于某些数据列可能存在被依赖关系而不能被简单删除,初始化也不保证能够删除 [AutoCSer.Sql.Model] 中指定的 DeleteColumnNames,请在程序运行前自行维护数据库表格。

写操作 Insert / Update / Delete 参考示例 AutoCSer\Example\OrmTable\NowTime.Write.cs
写操作事件 参考示例 AutoCSer\Example\OrmTable\NowTime.Events.cs

8. 如果在 [AutoCSer.Sql.Model] 中指定了 CacheType表格模型中间层中会生成一个名称为 sqlCache 的静态字段,用于指定数据表格的主索引缓存
在无法确定创建缓存参数的情况下会生成一个名称为 createCache 的静态方法,用于初始化创建数据表格的主索引缓存

对于临时性需求,该框架也可以当成简单的单表格 ORM 使用而无需静态代码生成

参考示例 AutoCSer\Example\OrmTable\OrmOnly.cs

相关测试项目包括 AutoCSer.TestCase.SqlModel / AutoCSer.TestCase.SqlTableCacheServer / AutoCSer.TestCase.SqlTableWeb