听棠.NET

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

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

Feedback

#1楼  回复 引用 查看   

2005-04-07 10:24 by Austin leng      
还没仔细看,晚上回去慢慢看,呵呵

#2楼  回复 引用   

2005-04-07 11:19 by 极速麻醉
支持!
工作有点忙!有时间再仔细看了。

#3楼  回复 引用 查看   

2005-04-07 14:25 by jlzhou      
觉得多帐套没什么用,完全可以设置另外的Demo应用环境来实现与主环境隔离。就像两个碗,一个盛菜,一个盛饭,没必要在碗里加个隔断来区分菜和饭。:-)

#4楼[楼主]  回复 引用 查看   

2005-04-07 14:32 by 听棠.NET      
@jlzhou :
错,提供这样的功能,是为以后的系统动态添加“帐套”作准备的。要是客户自建个帐套数据库,如果不提供“多帐套”功能,那要如何处理?
让客户自己修改XML配置??
再说了,客户就是要多帐套数据库同时运行,因为有的人正式帐套,有的人用Demo帐套。

#5楼  回复 引用 查看   

2005-04-07 14:37 by jlzhou      
@tintown:
哈哈,我觉得可以在部署时,多部署一套用来Demo的帐套就可以了,如果提供用户可以自行增加帐套功能,则另当别论。

#6楼[楼主]  回复 引用 查看   

2005-04-07 14:40 by 听棠.NET      
@jlzhou :
这就对了,我的这个功能就是想允许客户自定义“多帐套”,至于多帐套的设计那是业务层的事,至少SPL将支持这种功能了。
如果在部署时配置两个帐套数据库,那客户在登录时也要进行选择帐套,那么,不同的选择应该在不同的帐套数据库中执行。
所以这个功能非常有意义。。

#7楼  回复 引用   

2005-04-07 17:21 by baogong
支持,我觉得这个功能很有意义的。

可以在多个数据库间操作并进行处理,主要是这些数据库因为一些原因不能合并到这一块。

#8楼  回复 引用   

2005-04-08 01:22 by birdshome
最大的意义是用来做假账。

#9楼  回复 引用   

2005-04-25 14:04 by kknd
数据库的结构既然是一样的,那就创建多个数据库,用户访问的时候根据选择连接不同的数据库不就得了?

#10楼[楼主]  回复 引用 查看   

2005-04-25 16:14 by 听棠.NET      
@kknd :
对于,我就是用这种方式来对多数据库进行支持的。你说的就是我要的支持的效果。
不用持久层就象说的,非常简单的。
那你其他的ORM框架支持吗?比如NH是如何支持的呢??

#11楼  回复 引用   

2005-08-07 15:51 by 建平[未注册用户]
支持
我现在的系统就要求用户定义自己的帐套,
如果spl不支持,就不那么好处理了.

#12楼[楼主]  回复 引用 查看   

2005-08-09 08:52 by 听棠.NET      
@建平:
现在的SPL就是支持这种多帐套,我说的多帐套,自然是自定义帐套了,现在的ORM框架中只有SPL是支持这种方式的。

#13楼  回复 引用   

2005-12-09 15:30 by inger[未注册用户]
听棠大哥,你的SPL很好用,谢谢你
我有个问题:
“系统会有一个主数据库Master,多个帐套数据库Demo1、Demo2”
请问多套帐能不能让主数据库和帐套数据库同时存在,现在会因为一次
Setting.Instance().AppendDatabase("数据源名称",数据源类型DatabaseType枚举值,"连接字符串");
更会改变数据源,

也就是说,能不能同时支持多个数据源?

#14楼[楼主]  回复 引用 查看   

2005-12-09 17:45 by 听棠.NET      
@inger :
那个AppendDatabase是追加数据源,追加就是共存的意思,不是替代。
当你追加demo1,demo2的数据源以后,在程序中就可以使用"demo1"和"demo2"了,可以同时使用了。

#15楼  回复 引用   

2005-12-10 18:11 by inger[未注册用户]
OK,知道了,不提醒还真不能理解!谢谢

#16楼  回复 引用   

2006-09-24 20:36 by 云飞.NET[未注册用户]
您好,关于您的多账套处理,您提供了两个函数:
AppendDatabase(string name, DatabaseType databaseType, string connectionString, string ClassMapPath)
AppendDatabase(string name, DatabaseType databaseType, string connectionString)
我想问的是:如果我用了第二种方法,那么这个数据源的CLASSMAP信息怎么获取啊?而后又怎么对这种数据源的classmap进行操作呢?

#17楼  回复 引用   

2006-12-31 13:37 by wangwanttt[未注册用户]
真是个垃圾
我ACCESS数据库中的表已经有主键了,可它一直提示“XXX表无主键”

#18楼  回复 引用 查看   

2007-04-08 10:07 by qufo2008      
@wangwanttt

当你写出一个不垃圾的东西出来,再来骂老大,OK?


虽然我还没有正式用到项目中,我绝对支持听棠老大。