听棠.NET

用积极乐观的心态,面对压力
posts - 307, comments - 10812, trackbacks - 112, articles - 5
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

公告

SmartPersistenceLayer3.1讲解(9)---多帐套处理篇

Posted on 2005-04-07 09:38 听棠.NET 阅读(...) 评论(...) 编辑 收藏
 

SmartPersistenceLayer 3.1 多帐套处理篇

 提出问题

   这个“多帐套”的概念,只是因为多帐套是一个最典型的例子,找不到其他的词来描述,就直接命名为“多帐套”。

   比如一个ERP系统,在开始使用时,为了测试,客户一般会新建一个Demo帐套,然后客户在这个帐套的环境下进行一些Demo测试;当测试通过后,客户想要正式使用时,会新建一个正式的帐套。一般稍大型一点的系统都会允许进行多帐套设置,记得用友、金碟、SBO(SAP Business One)都有哦。

   这种多帐套的实现,在数据库层面上,体现为新建一个“帐套数据库”。比如系统会有一个主数据库Master,多个帐套数据库Demo1Demo2等,这些“帐套数据库”在Master中是有记录的,也就是用户在新建“帐套数据库”时,同时会在Master的某个表中进行记录,这样用户登录时就可以进行选择“帐套数据库”操作了。

   这些“帐套数据库”存在一个特点是:
数据库本身结构是固定的:因为在系统开发时,已经确定了数据库结构

         数据库之间是相同的:所有的这些“帐套数据库”其结构是完全相同的,因为是通过相同的语句生成的。

   然后,在我们的ORM开发模式中,数据库与业务实体是通过XML进行映射的,而且实体类也是已经定义好的。这导致实体的映射数据库被死死的绑定到了指定数据库了。

   而作为ORM开发模式,而且还应该能透明支持异构多数据库,也就是有可能两个完全相同的帐套,一个是在Sql Server中,另一个是在Oracle数据库中。

   由于导致实体映射的相对因定性,与系统运行状态下“多帐套”的灵活性产生冲突。

 

分析问题

   ORM开发模式下,实体的相对固定性,本身是一个局限性问题,因为使用了实体,就不能像SQL那样灵活,随意建个数据库就能操作,在ORM模式下,要是想让用户新建自己的表,实现可能会相对麻烦许多,因为在新建表的同时,要求新建相应的实体类与这映射。那这个编译也将成为问题。

而现在的“多帐套”问题,存在一个特点就是数据库结构没有改变,也就是同样的数据库结构,只是“数据源”不同了。因此,只要我们的ORM能支持动态设置实体的“数据源”就可以解决问题。

 

解决问题

   SPL中从3.1开始支持“多帐套”功能。在SPL的实体映射中,默认是有“数据源”的,也就是如果您的系统不需要“多帐套”功能,那么完全不要特殊的处理。

   数据源载入

   “多帐套”的情况会有两种,一种是“多帐套”数据库在设计时就已经确定,比如在DatabaseMap.xml中进行了两个“多帐套”数据源的设置:Demo1,Demo2,这两个数据库的结构完全一致,而实体默认是在Demo1中的。这种情况下,数据源Demo1Demo2在系统启动时就已经载入了,因此可以直接使用这些“数据源”。

另一种情况,就是用户在系统运行时,用户自己添加的帐套,那么在这种情况下,新建的“数据源”Demo2DatabaseMap.xml配置中没有的。因此,此Demo2的“数据源”需要在系统运行时,动态载入。

比如新建的Demo2Master主数据库中进行了记录,那么读取Master中的Demo2配置信息,进行动态“数据源”载入:

Setting.Instance().AppendDatabase("数据源名称",数据源类型DatabaseType枚举值,"连接字符串");

例如:

Setting.Instance().AppendDatabase("Demo2",DatabaseType.Odbc,"Driver={SQL Server};Server=localhost;UID=sa;Pwd=both;Database=Northwind");

这样,我们就可以使用此新的“数据源”了。

 

使用

实体操作

 使用EntityDatabaseName属性即可(注意此DatabaseName是“数据源名称”而不是指数据库的名称,前上面所示的是Demo2,而不是Narthwind。)如:

StudentEntity Student=new Student();

Student.DatabaseName
=”Demo2”;

Student.Id
=1;

Student.Retrieve();    
//此Retrieve就是从新的Demo2数据源操作了。

…..

SaveDelete也是一样的,只要在使用前指明一下DatabaseName即可。

 

如果不需要“多帐套”,不需要指定DatabaseName,实体会采用自已默认的“数据源”

 

RetrieveCriteria操作

Criteria的“多帐套”采用两种方式:实例化时就指定

 RetrieveCriteria Rc=new RetrieveCriteria(typeof(StudentEntity),”Demo2”);

或者:

 

RetrieveCriteria Rc=new RetrieveCriteria(typeof(StudentEntity));

Rc.DatabaseName
=”Demo2”;    //指定DatabaseName属性

Rc.AsDataTable();           
//操作在指定的“数据源”上执行



其他的UpdateCriteriaDeleteCriteria也是一样的,只要在执行前指定DatabaseName

 

 

Query操作

 Query也支持“多帐套”功能,实现方式也是:

  

 Query q=new Query(typeof(StudentEntity),”Demo2”);

 或者

 

 

  Query q=new Query(typeof(StudentEntity));

   q.DatabaseName
=”Demo2”;

   …..

 由于Query是多数据表联合查询,会同时存在多个Query对象,而一次查询只能是针对一个数据库进行的。为了支持“多帐套”,在多个Query中,只有最后负责执行Query的对象才是真正决定在哪个数据库上执行。也就是负责q.Execute()或者q.ExecuteScalar()qDatabaseName才是执行的数据源,比如:

 

Query Q1=new Query(….);

Q1.DatabaseName
=”Demo1”;



Query Q2
=new Query(…);

Q2.DatabaseName
=”Demo2”;



Q2.Execute();           
//只执行只在Demo2数据源上执行

 

 

PS:此功能为SPL3.1支持,即将发布

                                               听棠

                                              2005-4-7