SmartPersistenceLayer 3.1 之 多帐套处理篇
提出问题
这个“多帐套”的概念,只是因为多帐套是一个最典型的例子,找不到其他的词来描述,就直接命名为“多帐套”。
比如一个ERP系统,在开始使用时,为了测试,客户一般会新建一个Demo帐套,然后客户在这个帐套的环境下进行一些Demo测试;当测试通过后,客户想要正式使用时,会新建一个正式的帐套。一般稍大型一点的系统都会允许进行多帐套设置,记得用友、金碟、SBO(SAP Business One)都有哦。
这种多帐套的实现,在数据库层面上,体现为新建一个“帐套数据库”。比如系统会有一个主数据库Master,多个帐套数据库Demo1、Demo2等,这些“帐套数据库”在Master中是有记录的,也就是用户在新建“帐套数据库”时,同时会在Master的某个表中进行记录,这样用户登录时就可以进行选择“帐套数据库”操作了。
这些“帐套数据库”存在一个特点是:
数据库本身结构是固定的:因为在系统开发时,已经确定了数据库结构
数据库之间是相同的:所有的这些“帐套数据库”其结构是完全相同的,因为是通过相同的语句生成的。
然后,在我们的ORM开发模式中,数据库与业务实体是通过XML进行映射的,而且实体类也是已经定义好的。这导致实体的映射数据库被死死的绑定到了指定数据库了。
而作为ORM开发模式,而且还应该能透明支持异构多数据库,也就是有可能两个完全相同的帐套,一个是在Sql Server中,另一个是在Oracle数据库中。
由于导致实体映射的相对因定性,与系统运行状态下“多帐套”的灵活性产生冲突。
分析问题
在ORM开发模式下,实体的相对固定性,本身是一个局限性问题,因为使用了实体,就不能像SQL那样灵活,随意建个数据库就能操作,在ORM模式下,要是想让用户新建自己的表,实现可能会相对麻烦许多,因为在新建表的同时,要求新建相应的实体类与这映射。那这个编译也将成为问题。
而现在的“多帐套”问题,存在一个特点就是数据库结构没有改变,也就是同样的数据库结构,只是“数据源”不同了。因此,只要我们的ORM能支持动态设置实体的“数据源”就可以解决问题。
解决问题
在SPL中从3.1开始支持“多帐套”功能。在SPL的实体映射中,默认是有“数据源”的,也就是如果您的系统不需要“多帐套”功能,那么完全不要特殊的处理。
数据源载入
“多帐套”的情况会有两种,一种是“多帐套”数据库在设计时就已经确定,比如在DatabaseMap.xml中进行了两个“多帐套”数据源的设置:Demo1,Demo2,这两个数据库的结构完全一致,而实体默认是在Demo1中的。这种情况下,数据源Demo1与Demo2在系统启动时就已经载入了,因此可以直接使用这些“数据源”。
另一种情况,就是用户在系统运行时,用户自己添加的帐套,那么在这种情况下,新建的“数据源”Demo2在DatabaseMap.xml配置中没有的。因此,此Demo2的“数据源”需要在系统运行时,动态载入。
比如新建的Demo2在Master主数据库中进行了记录,那么读取Master中的Demo2配置信息,进行动态“数据源”载入:
Setting.Instance().AppendDatabase("数据源名称",数据源类型DatabaseType枚举值,"连接字符串");
例如:
Setting.Instance().AppendDatabase("Demo2",DatabaseType.Odbc,"Driver={SQL Server};Server=localhost;UID=sa;Pwd=both;Database=Northwind");
这样,我们就可以使用此新的“数据源”了。
使用
实体操作
使用Entity的DatabaseName属性即可(注意此DatabaseName是“数据源名称”而不是指数据库的名称,前上面所示的是Demo2,而不是Narthwind。)如:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
Save与Delete也是一样的,只要在使用前指明一下DatabaseName即可。
如果不需要“多帐套”,不需要指定DatabaseName,实体会采用自已默认的“数据源”
RetrieveCriteria操作
Criteria的“多帐套”采用两种方式:实例化时就指定
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
或者:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
其他的UpdateCriteria、DeleteCriteria也是一样的,只要在执行前指定DatabaseName。
Query操作
Query也支持“多帐套”功能,实现方式也是:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
或者 :
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
由于Query是多数据表联合查询,会同时存在多个Query对象,而一次查询只能是针对一个数据库进行的。为了支持“多帐套”,在多个Query中,只有最后负责执行Query的对象才是真正决定在哪个数据库上执行。也就是负责q.Execute()或者q.ExecuteScalar()的q的DatabaseName才是执行的数据源,比如:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
PS:此功能为SPL3.1支持,即将发布
听棠